efps-version
elf 1 year ago
parent 85fe14db3e
commit db8eab70c8

@ -8,6 +8,8 @@ use App\Helper\Efps\Result;
use App\Helper\Efps\Signer;
use App\Helper\Log;
use App\Helper\Platform\Notification;
use App\Helper\Platform\Signer as PlatformSigner;
use App\Helper\StringHelper;
use App\Model\App;
use App\Model\Order;
use App\Model\RefundOrder;
@ -139,6 +141,9 @@ class NotifyController extends AbstractController
}
protected function notify($url, $app, $data) {
if (empty($url)) {
return 'empty url';
}
$params = [
'app_id' => $app->app_id,
'nonce_str' => StringHelper::getRandomString(32),

@ -1,36 +0,0 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace App\Controller\Payment;
use App\Helper\Log;
use App\Model\Order;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Psr\Http\Message\ResponseInterface as Psr7ResponseInterface;
class PageController extends AbstractController
{
public function index(RequestInterface $request, ResponseInterface $response): Psr7ResponseInterface
{
$orderNo = $request->input('order_no', '');
Log::info('redirectToOut orderNo:' . $orderNo, [], 'omipay');
if (! $orderNo) {
return '订单号错误';
}
$order = Order::where('order_no', $orderNo)->first();
if (! $order) {
return '订单号错误';
}
Log::info('redirectToOut url:' . $order->redirect_url, [], 'omipay');
return $response->redirect($order->redirect_url);
}
}

@ -4,18 +4,6 @@ declare(strict_types=1);
namespace App\Controller\Payment;
use App\Exception\BusinessException;
use App\Helper\Efps\Api;
use App\Model\Order;
use App\Model\RefundOrder;
use App\Request\BindCardConfirmRequest;
use App\Request\BindCardRequest;
use App\Request\PaymentQueryRequest;
use App\Request\ProtocolPayConfirmRequest;
use App\Request\ProtocolPayPreRequest;
use App\Request\RefundQueryRequest;
use App\Request\RefundRequest;
use App\Request\UnBindCardRequest;
use Hyperf\HttpServer\Contract\RequestInterface;
use App\Service\PaymentService;
@ -30,32 +18,20 @@ class PayController extends AbstractController
public function bindCard(RequestInterface $request)
{
$req = new BindCardRequest($request->all());
$result = Api::bindCard($req->getData());
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
return $this->success($result->getData());
$data = $this->paymentService->bindCard($request->all());
return $this->success($data);
}
public function bindCardConfirm(RequestInterface $request)
{
$req = new BindCardConfirmRequest($request->all());
$result = Api::bindCardConfirm($req->getData());
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
return $this->success($result->getData());
$data = $this->paymentService->bindCardConfirm($request->all());
return $this->success($data);
}
public function unBindCard(RequestInterface $request)
{
$req = new UnBindCardRequest($request->all());
$result = Api::unBindCard($req->getData());
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
return $this->success($result->getData());
$data = $this->paymentService->unBindCard($request->all());
return $this->success($data);
}
public function protocolPayPreRequest(RequestInterface $request)
@ -71,82 +47,17 @@ class PayController extends AbstractController
}
public function refund(RequestInterface $request) {
$req = new RefundRequest($request->all());
$app = $req->getApp();
$data = $req->getData();
$refundOrder = new RefundOrder();
$refundOrder->app_id = $app->app_id;
$refundOrder->out_order_no = $data['outTradeNo'] ?: '';
$refundOrder->out_refund_order_no = $data['outRefundNo'] ?: '';
$refundOrder->order_amount = $data['amount'] ?: '';
$refundOrder->refund_amount = $data['refundAmount'] ?: '';
$refundOrder->remark = $data['remark'] ?: '';
$refundOrder->notify_url = $data['notifyUrl'] ?: '';
$result = Api::refund($data);
if (!$result->isSuccess()) {
$refundOrder->status = RefundOrder::STATUS_APPLY_FAILED;
$refundOrder->error_code = $result->getCode();
$refundOrder->error_msg = $result->getMessage();
$refundOrder->save();
throw new BusinessException($result->getMessage());
}
$refundOrder->status = RefundOrder::STATUS_APPLY_SUCCESS;
$refundOrder->save();
return $this->success($result->getData());
$data = $this->paymentService->refund($request->all());
return $this->success($data);
}
public function refundQuery(RequestInterface $request) {
$req = new RefundQueryRequest($request->all());
$data = $req->getData();
$result = Api::refundQuery($data);
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
$order = RefundOrder::where('out_refund_order_no', $result->get('outRefundNo'))
->where('status', RefundOrder::STATUS_APPLY_SUCCESS)
->first();
if ($order) {
$this->paymentService->handleRefundResult($result, $order);
}
return $this->success(
$result->getData([
'outRefundNo',
'transactionNo',
'amount',
'refundAmount',
'refundState'
])
);
$data = $this->paymentService->refundQuery($request->all());
return $this->success($data);
}
public function paymentQuery(RequestInterface $request) {
$req = new PaymentQueryRequest($request->all());
$data = $req->getData();
$result = Api::paymentQuery($data);
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
$order = Order::where('out_order_no', $result->get('outTradeNo'))
->where('status', Order::STATUS_WAIT_PAY)
->first();
if ($order) {
$this->paymentService->handlePayResult($result, $order);
}
return $this->success(
$result->getData([
'outTradeNo',
'transactionNo',
'payState',
'procedureFee',
'amount'
])
);
$data = $this->paymentService->paymentQuery($request->all());
return $this->success($data);
}
}

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace App\Controller\Recharge;
use App\Constants\ResultCode;
use App\Helper\Result;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Psr\Container\ContainerInterface;
abstract class AbstractController
{
/**
* @Inject
* @var ContainerInterface
*/
protected ContainerInterface $container;
/**
* @Inject
* @var RequestInterface
*/
protected RequestInterface $request;
/**
* @Inject
* @var ResponseInterface
*/
protected ResponseInterface $response;
protected function success(array $data = [], string $message = '成功'): Result
{
return new Result(ResultCode::SUCCESS, $message, $data);
}
}

@ -0,0 +1,243 @@
<?php
declare(strict_types=1);
namespace App\Controller\Recharge;
use App\Exception\BusinessException;
use App\Exception\UnauthorizedException;
use App\Helper\Redis;
use App\Helper\StringHelper;
use App\Model\App;
use App\Model\BankCard;
use App\Model\Order;
use App\Model\User;
use App\Service\PaymentService;
use Hyperf\HttpServer\Contract\RequestInterface;
class RechargeController extends AbstractController
{
private PaymentService $paymentService;
public function __construct(PaymentService $paymentService)
{
$this->paymentService = $paymentService;
}
public function recharge(RequestInterface $request) {
$app = App::query()->orderBy('id', 'asc')->first();
$name = $request->input('name');
if (empty($name)) {
throw new BusinessException('请输入姓名');
}
$amount = $request->input('amount');
if (empty($amount)) {
throw new BusinessException('请输入金额');
}
if (!is_numeric($amount)) {
throw new BusinessException('请输入金额');
}
if ($amount <= 0) {
throw new BusinessException('金额需大于0');
}
$cardNo = $request->input('cardNo');
if (empty($cardNo)) {
throw new BusinessException('请输入身份证号');
}
$mobile = $request->input('mobile');
if (empty($mobile)) {
throw new BusinessException('请输入手机号');
}
$bankCardNo = $request->input('bankCardNo');
if (empty($bankCardNo)) {
throw new BusinessException('请输入银行卡号');
}
$memberId = $this->paymentService->generateMemberId($app->app_key, $cardNo);
$user = User::where('member_id', $memberId)->first();
$bankCard = null;
if ($user) {
$bankCard = BankCard::where('member_id', $user->member_id)->where('bank_card_no', $bankCardNo)->where('status', BankCard::STATUS_ACTIVE)->first();
}
if ($bankCard) {
$outTradeNo = StringHelper::generateOrderNo();
$nextStep = 'confirm-pay';
$bizData = $this->paymentService->protocolPayPreRequest($this->buildPrepayParams($user->member_id, $outTradeNo, $bankCard->protocol, intval($amount * 100), $app));
} else {
$mchOrderNo = StringHelper::generateBankCardOrderNo();
$nextStep = 'confirm-bind';
$bizData = $this->paymentService->bindCard($this->buildBindCardParams($mchOrderNo, $memberId, $name, $cardNo, $mobile, $bankCardNo, $app));
}
return $this->success([
'nextStep' => $nextStep,
'memberId' => $memberId,
'bizData' => $bizData
]);
}
public function confirmBindCard(RequestInterface $request) {
$app = App::query()->orderBy('id', 'asc')->first();
$memberId = $request->input('memberId');
$smsNo = $request->input('smsNo');
$smsCode = $request->input('smsCode');
$bizData = $this->paymentService->bindCardConfirm($this->buildComfirmBindCardParams($memberId, $smsNo, $smsCode, $app));
return $this->success([
'memberId' => $memberId,
'bizData' => $bizData
]);
}
public function confirmPay(RequestInterface $request) {
$app = App::query()->orderBy('id', 'asc')->first();
$memberId = $request->input('memberId');
$token = $request->input('token');
$protocol = $request->input('protocol');
$smsCode = $request->input('smsCode');
$bizData = $this->paymentService->protocolPayConfirm($this->buildConfirmPayParams($token, $protocol, $smsCode, $app));
return $this->success([
'memberId' => $memberId,
'bizData' => ['outTradeNo' => $bizData['outTradeNo']]
]);
}
private function buildBindCardParams($mchOrderNo, $memberId, $name, $cardNo, $mobile, $bankCardNo, $app)
{
$params = [
'app_id' => $app->app_id,
'timestamp' => time(),
'nonce_str' => StringHelper::getRandomString(32),
'data' => json_encode([
'mchtOrderNo' => $mchOrderNo,
'memberId' => $memberId,
'userName' => $name,
'phoneNum' => $mobile,
'bankCardNo' => $bankCardNo,
'bankCardType' => 'debit',
'certificatesNo' => $cardNo,
]),
];
$sign = \App\Helper\Platform\Signer::sign($params, $app->app_key);
$params['sign'] = $sign;
return $params;
}
private function buildPrepayParams($memberId, $outTradeNo, $protocol, $amount, $app)
{
$params = [
'app_id' => $app->app_id,
'timestamp' => time(),
'nonce_str' => StringHelper::getRandomString(32),
'data' => json_encode([
'memberId' => $memberId,
'outTradeNo' => $outTradeNo,
'protocol' => $protocol,
'payAmount' => $amount,
]),
];
$sign = \App\Helper\Platform\Signer::sign($params, $app->app_key);
$params['sign'] = $sign;
return $params;
}
private function buildConfirmPayParams($token, $protocol, $smsCode, $app)
{
$params = [
'app_id' => $app->app_id,
'timestamp' => time(),
'nonce_str' => StringHelper::getRandomString(32),
'data' => json_encode([
'token' => $token,
'protocol' => $protocol,
'smsCode' => $smsCode,
]),
];
$sign = \App\Helper\Platform\Signer::sign($params, $app->app_key);
$params['sign'] = $sign;
return $params;
}
private function buildComfirmBindCardParams($memberId, $smsNo, $smsCode, $app)
{
$params = [
'app_id' => $app->app_id,
'timestamp' => time(),
'nonce_str' => StringHelper::getRandomString(32),
'data' => json_encode([
'memberId' => $memberId,
'smsNo' => $smsNo,
'smsCode' => $smsCode,
]),
];
$sign = \App\Helper\Platform\Signer::sign($params, $app->app_key);
$params['sign'] = $sign;
return $params;
}
public function orders(RequestInterface $request)
{
$page = $request->input('page', 1);
$pageSize = $request->input('pageSize', 20);
$token = $request->input('token');
$value = Redis::get('token:' . $token);
$users = $this->getUsers();
if (empty($value) || !isset($users[$value])) {
throw new UnauthorizedException();
}
$offset = ($page - 1) * $pageSize;
$orders = Order::query()->orderBy('id', 'desc')->offset($offset)->limit($pageSize)->get();
$protocols = $orders->pluck('protocol');
$bankCards = BankCard::whereIn('protocol', $protocols)->get();
$bankCards = $bankCards->keyBy('protocol');
$records = [];
foreach ($orders as $order) {
$bankCard = $bankCards[$order->protocol] ?? null;
$records[] = [
'out_order_no' => $order->out_order_no,
'payed_at' => $order->payed_at,
'status' => $order->status,
'amount' => number_format($order->amount / 100, 2, '.', ''),
'real_name' => $bankCard ? $bankCard->real_name : '',
'bank_card_no' => $bankCard ? $bankCard->bank_card_no : '',
'mobile' => $bankCard ? $bankCard->mobile : '',
'card_no' => $bankCard ? $bankCard->card_no : '',
'status_text' => $order->getStatusText(),
];
}
$total = Order::query()->count();
return $this->success([
'records' => $records,
'total' => $total,
]);
}
public function login(RequestInterface $request)
{
$username = $request->input('username');
$password = $request->input('password');
if (empty($username) || empty($password)) {
throw new BusinessException('账号或密码错误');
}
$users = $this->getUsers();
if (isset($users[$username]) && $users[$username] === $password) {
$token = md5(microtime() . $username . $password);
Redis::set('token:' . $token, $username);
Redis::expire('token:' . $token, 60*60);
return $this->success(['token' => $token]);
}
throw new BusinessException('账号或密码错误');
}
private function getUsers() {
return [
'owx0tlx' => 'lSoLW28NxtMlxUazC8p',
'ioexlp2' => 'wwU8Ir3Xp0rxXssA9NV'
];
}
}

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace App\Exception;
use App\Constants\ResultCode;
use Throwable;
class UnauthorizedException extends BasicException
{
protected $code = ResultCode::UNAUTHORIZED;
}

@ -17,4 +17,8 @@ class RedisKey
public static function getGenerateRequestIdKey($timestamp) {
return 'gennerate_request_id:' . date('YmdHi', $timestamp);
}
public static function getGenerateBindCardKey($timestamp) {
return 'gennerate_bank_card:' . date('YmdHi', $timestamp);
}
}

@ -46,4 +46,15 @@ class StringHelper
$incrId = str_pad($incrId, $padLength, '0', STR_PAD_LEFT);
return date('YmdHis', $now) . $incrId;
}
public static function generateBankCardOrderNo() {
$now = time();
$key = RedisKey::getGenerateBindCardKey($now);
$incrId = Redis::incr($key);
$incrId = '' . $incrId;
Redis::expire($key, 5*60);
$padLength = 6 - strlen($incrId);
$incrId = str_pad($incrId, $padLength, '0', STR_PAD_LEFT);
return date('YmdHis', $now) . $incrId;
}
}

@ -6,5 +6,9 @@ namespace App\Model;
class BankCard extends Model
{
public const STATUS_WAIT_CONFIRM = 1;
public const STATUS_ACTIVE = 2;
public const STATUS_UNBIND = 3;
protected $table = 'bank_cards';
}

@ -13,4 +13,14 @@ class Order extends Model
public const STATUS_FAILED = 9;
protected $table = 'orders';
public function getStatusText() {
$statusMap = [
self::STATUS_APPLY_FAIL => '申请失败',
self::STATUS_WAIT_PAY => '待支付',
self::STATUS_PAYED => '支付成功',
self::STATUS_FAILED => '支付失败',
];
return $statusMap[$this->status];
}
}

@ -10,20 +10,32 @@ use App\Helper\Efps\Result;
use App\Helper\Redis;
use App\Helper\RedisKey;
use App\Model\App;
use App\Model\BankCard;
use App\Model\Order;
use App\Model\RefundOrder;
use App\Model\User;
use App\Request\BindCardConfirmRequest;
use App\Request\BindCardRequest;
use App\Request\PaymentQueryRequest;
use App\Request\ProtocolPayConfirmRequest;
use App\Request\ProtocolPayPreRequest;
use App\Request\RefundQueryRequest;
use App\Request\RefundRequest;
use App\Request\UnBindCardRequest;
class PaymentService extends AbstractService
{
public function generateMemberId($appKey, $cardNo) {
return md5($appKey . '-' . $cardNo);
}
public function createOrder(App $app, array $params) {
$order = new Order();
$order->app_id = $app->app_id;
$order->out_order_no = $params['outTradeNo'] ?: '';
$order->amount = $params['payAmount'] ?: 0;
$order->notify_url = $params['notifyUrl'] ?: '';
$order->order_info = json_encode($params['orderInfo'] ?: [], JSON_UNESCAPED_UNICODE);
$order->out_order_no = $params['outTradeNo'] ?? '';
$order->amount = $params['payAmount'] ?? 0;
$order->notify_url = $params['notifyUrl'] ?? '';
$order->order_info = json_encode($params['orderInfo'] ?? [], JSON_UNESCAPED_UNICODE);
return $order;
}
@ -117,4 +129,183 @@ class PaymentService extends AbstractService
$this->handlePayResult($result, $order);
return $result->getData();
}
public function bindCard($params) {
$req = new BindCardRequest($params);
$app = $req->getApp();
$reqData = $req->getData();
$memberId = $this->generateMemberId($app->app_key, $reqData['certificatesNo']);
$reqData['memberId'] = $memberId;
$bankCard = BankCard::where('app_id', $app->app_id)
->where('member_id', $memberId)
->where('bank_card_no', $reqData['bankCardNo'])
->where('status', BankCard::STATUS_ACTIVE)
->first();
if ($bankCard) {
throw new BusinessException('该卡已绑定');
}
$result = Api::bindCard($reqData);
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
$user = User::where('member_id', $memberId)->first();
if (!$user) {
$user = new User();
$user->member_id = $memberId;
$user->app_id = $app->app_id;
$user->real_name = $reqData['userName'];
$user->card_no = $reqData['certificatesNo'];
$user->mobile = $reqData['phoneNum'];
$user->save();
}
$bankCard = new BankCard();
$bankCard->member_id = $memberId;
$bankCard->app_id = $app->app_id;
$bankCard->real_name = $reqData['userName'];
$bankCard->card_no = $reqData['certificatesNo'];
$bankCard->mobile = $reqData['phoneNum'];
$bankCard->sms_no = $result->get('smsNo', '');
$bankCard->bank_card_no = $reqData['bankCardNo'];
$bankCard->bank_card_type = $reqData['bankCardType'];
$bankCard->protocol = $result->get('protocol', '');
$bankCard->expired = $reqData['expired'] ?? '';
$bankCard->cvn = $reqData['cvn'] ?? '';
$bankCard->status = BankCard::STATUS_WAIT_CONFIRM;
$bankCard->save();
return array_merge($result->getData(), ['memberId' => $memberId]);
}
public function bindCardConfirm($params)
{
$req = new BindCardConfirmRequest($params);
$app = $req->getApp();
$reqData = $req->getData();
$bankCard = BankCard::where('app_id', $app->app_id)
->where('member_id', $reqData['memberId'])
->where('sms_no', $reqData['smsNo'])
->where('status', BankCard::STATUS_WAIT_CONFIRM)
->first();
if (!$bankCard) {
throw new BusinessException('绑卡申请不存在');
}
$result = Api::bindCardConfirm($reqData);
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
$bankCard->status = BankCard::STATUS_ACTIVE;
$bankCard->protocol = $result->get('protocol', '');
$bankCard->save();
return $result->getData();
}
public function refundQuery($params)
{
$req = new RefundQueryRequest($params);
$data = $req->getData();
$result = Api::refundQuery($data);
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
$order = RefundOrder::where('out_refund_order_no', $result->get('outRefundNo'))
->where('status', RefundOrder::STATUS_APPLY_SUCCESS)
->first();
if ($order) {
$this->handleRefundResult($result, $order);
}
return $result->getData([
'outRefundNo',
'transactionNo',
'amount',
'refundAmount',
'refundState'
]);
}
public function paymentQuery($params)
{
$req = new PaymentQueryRequest($params);
$data = $req->getData();
$result = Api::paymentQuery($data);
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
$order = Order::where('out_order_no', $result->get('outTradeNo'))
->where('status', Order::STATUS_WAIT_PAY)
->first();
if ($order) {
$this->handlePayResult($result, $order);
}
return $result->getData([
'outTradeNo',
'transactionNo',
'payState',
'procedureFee',
'amount'
]);
}
public function unBindCard($params)
{
$req = new UnBindCardRequest($params);
$app = $req->getApp();
$reqData = $req->getData();
$bankCard = BankCard::where('app_id', $app->app_id)
->where('member_id', $reqData['memberId'])
->where('protocol', $reqData['protocol'])
->where('status', BankCard::STATUS_ACTIVE)
->first();
if (!$bankCard) {
throw new BusinessException('绑卡不存在');
}
$result = Api::unBindCard($reqData);
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
$bankCard->status = BankCard::STATUS_UNBIND;
$bankCard->save();
return $result->getData();
}
public function refund($params)
{
$req = new RefundRequest($params);
$app = $req->getApp();
$data = $req->getData();
$refundOrder = new RefundOrder();
$refundOrder->app_id = $app->app_id;
$refundOrder->out_order_no = $data['outTradeNo'] ?: '';
$refundOrder->out_refund_order_no = $data['outRefundNo'] ?: '';
$refundOrder->order_amount = $data['amount'] ?: '';
$refundOrder->refund_amount = $data['refundAmount'] ?: '';
$refundOrder->remark = $data['remark'] ?: '';
$refundOrder->notify_url = $data['notifyUrl'] ?: '';
$result = Api::refund($data);
if (!$result->isSuccess()) {
$refundOrder->status = RefundOrder::STATUS_APPLY_FAILED;
$refundOrder->error_code = $result->getCode();
$refundOrder->error_msg = $result->getMessage();
$refundOrder->save();
throw new BusinessException($result->getMessage());
}
$refundOrder->status = RefundOrder::STATUS_APPLY_SUCCESS;
$refundOrder->save();
return $result->getData();
}
}

@ -37,6 +37,8 @@ return [
Constant::OPTION_MAX_REQUEST => 100000,
Constant::OPTION_SOCKET_BUFFER_SIZE => 2 * 1024 * 1024,
Constant::OPTION_BUFFER_OUTPUT_SIZE => 2 * 1024 * 1024,
Constant::OPTION_DOCUMENT_ROOT => BASE_PATH . '/public',
Constant::OPTION_ENABLE_STATIC_HANDLER => true,
],
'callbacks' => [
Event::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],

@ -4,6 +4,7 @@ declare(strict_types=1);
use App\Controller\Payment\NotifyController;
use App\Controller\Payment\PayController;
use App\Controller\Recharge\RechargeController;
use Hyperf\HttpServer\Router\Router;
Router::get('/favicon.ico', function () {
@ -22,6 +23,14 @@ Router::addGroup('/payment',function () {
Router::post('/payment-query', [PayController::class, 'paymentQuery']);
}, ['middleware' => [\App\Middleware\RequestLogMiddleware::class]]);
Router::addGroup('/recharge',function () {
Router::post('/recharge', [RechargeController::class, 'recharge']);
Router::post('/confirm-bind-card', [RechargeController::class, 'confirmBindCard']);
Router::post('/confirm-pay', [RechargeController::class, 'confirmPay']);
Router::post('/orders', [RechargeController::class, 'orders']);
Router::post('/login', [RechargeController::class, 'login']);
});
Router::addGroup('/notify',function () {
Router::addRoute(['GET', 'POST'], '/payment', [NotifyController::class, 'payment']);
Router::addRoute(['GET', 'POST'], '/refund', [NotifyController::class, 'refund']);

@ -22,17 +22,16 @@ CREATE TABLE `request_logs` (
CREATE TABLE `users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`request_id` varchar(22) not null COMMENT '请求ID',
`app_id` varchar(16) NOT NULL COMMENT '应用ID',
`member_id` varchar(20) not null default '',
`merId` varchar(50) not null default '',
`member_id` varchar(32) not null default '',
`real_name` varchar(20) not null default '',
`card_no` varchar(32) not null default '',
`mobile` varchar(15) not null default '',
`card_valid_to` varchar(10) default NULL COMMENT '身份证有效期',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `idx_appid` (`app_id`) USING BTREE,
KEY `idx_memberid` (`member_id`) USING BTREE,
KEY `idx_cardno` (`card_no`) USING BTREE,
KEY `idx_createdat` (`created_at`) USING BTREE,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC;
@ -48,7 +47,8 @@ CREATE TABLE `bank_cards` (
`bank_card_type` varchar(10) not null default '',
`sms_no` varchar(32) NOT NULL DEFAULT '',
`protocol` varchar(32) NOT NULL DEFAULT '',
`bind_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '支付时间',
`expired` varchar(4) NOT NULL DEFAULT '',
`cvn` varchar(10) NOT NULL DEFAULT '',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

@ -0,0 +1,170 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- import CSS -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<title>充值</title>
</head>
<body>
<div id="app">
<el-container>
<el-header style="text-align: center;">充值</el-header>
<el-main>
<el-row>
<el-col :span="24">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="姓名">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="手机号">
<el-input v-model="form.mobile"></el-input>
</el-form-item>
<el-form-item label="身份证号">
<el-input v-model="form.cardNo"></el-input>
</el-form-item>
<el-form-item label="银行卡号">
<el-input v-model="form.bankCardNo"></el-input>
</el-form-item>
<el-form-item label="充值金额">
<el-input-number v-model="form.amount" :min="1" :max="100000" label="充值金额"></el-input-number>
</el-form-item>
<el-form-item label="备注">
<el-input type="textarea" v-model="form.remark"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="recharge">立即充值</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
</el-main>
</el-container>
<el-dialog title="绑卡验证码" :visible.sync="bindConfirmVisible" width="30%">
<el-form :model="bindConfirmForm" label-width="80px">
<el-form-item label="验证码">
<el-input v-model="bindConfirmForm.smsCode" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="bindConfirmVisible = false">取 消</el-button>
<el-button type="primary" @click="bindConfirm">确 定</el-button>
</div>
</el-dialog>
<el-dialog title="支付验证码" :visible.sync="payConfirmVisible" width="30%">
<el-form :model="payConfirmForm" label-width="80px">
<el-form-item label="验证码">
<el-input v-model="payConfirmForm.smsCode" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="payConfirmVisible = false">取 消</el-button>
<el-button type="primary" @click="payConfirm">确 定</el-button>
</div>
</el-dialog>
</div>
</body>
<!-- import Vue before Element -->
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://unpkg.com/axios@1.1.2/dist/axios.min.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
bindConfirmVisible: false,
bindConfirmForm: {
smsCode: '',
smsNo: '',
memberId: ''
},
payConfirmVisible: false,
payConfirmForm: {
smsCode: '',
memberId: '',
token: '',
protocol: ''
},
form: {
name: '饶丽秀',
mobile: '13817896134',
cardNo: '350824199001045864',
bankCardNo: '6212261402022689613',
amount: 1,
remark: ''
}
}
},
methods: {
recharge() {
axios.post('/recharge/recharge', this.form)
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
return this.$message.error(response.data.message);
}
if (result.data.nextStep == 'confirm-bind') {
this.bindConfirmVisible = true;
this.bindConfirmForm.memberId = result.data.memberId;
this.bindConfirmForm.smsNo = result.data.bizData.smsNo;
console.log(this.bindConfirmForm)
} else if (result.data.nextStep == 'confirm-pay') {
this.payConfirmVisible = true;
this.payConfirmForm.memberId = result.data.memberId;
this.payConfirmForm.protocol = result.data.bizData.protocol;
this.payConfirmForm.token = result.data.bizData.token;
console.log(this.payConfirmForm)
}
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
},
bindConfirm() {
axios.post('/recharge/confirm-bind-card', this.bindConfirmForm)
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
return this.$message.error(response.data.message);
}
this.bindConfirmVisible = false;
this.recharge();
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
},
payConfirm() {
axios.post('/recharge/confirm-pay', this.payConfirmForm)
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
return this.$message.error(response.data.message);
}
this.payConfirmVisible = false;
this.$message.success('支付成功');
this.$alert('请记住您的订单号:' + result.data.bizData.outTradeNo , '支付成功', {
confirmButtonText: '确定',
callback: action => {
}
});
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
}
}
})
</script>
</html>

@ -0,0 +1,158 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- import CSS -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<title>充值记录</title>
</head>
<body>
<div id="app">
<el-container>
<el-header style="text-align: center;">充值记录</el-header>
<el-main>
<el-row>
<el-col :span="24">
<el-table
:data="records"
style="width: 100%">
<el-table-column
prop="out_order_no"
label="订单号"
width="180">
</el-table-column>
<el-table-column
prop="real_name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="card_no"
label="身份证号">
</el-table-column>
<el-table-column
prop="bank_card_no"
label="银行卡号">
</el-table-column>
<el-table-column
prop="mobile"
label="手机号">
</el-table-column>
<el-table-column
prop="amount"
label="充值金额">
</el-table-column>
<el-table-column
prop="payed_at"
label="充值时间">
</el-table-column>
<el-table-column
prop="status_text"
label="状态">
</el-table-column>
</el-table>
<el-pagination
background
layout="prev, pager, next"
@current-change="handleCurrentChange"
:page-size="pageSize"
:total="total">
</el-pagination>
</el-col>
</el-row>
</el-main>
</el-container>
<el-dialog title="登录" :visible.sync="loginVisible" width="30%">
<el-form :model="loginer" label-width="80px">
<el-form-item label="账号">
<el-input v-model="loginer.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input v-model="loginer.password" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="loginVisible = false">取 消</el-button>
<el-button type="primary" @click="login">确 定</el-button>
</div>
</el-dialog>
</div>
</body>
<!-- import Vue before Element -->
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://unpkg.com/axios@1.1.2/dist/axios.min.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
records: [],
total: 0,
pageSize: 20,
loginVisible: false,
loginer: {
username: '',
password: ''
}
}
},
created() {
if (!window.sessionStorage.getItem('token')) {
this.loginVisible = true;
return this.$message.error('请先登录');
}
this.searchList();
},
methods: {
searchList(page) {
let data = {
token: window.sessionStorage.getItem('token'),
page: page,
pageSize: this.pageSize
}
axios.post('/recharge/orders', data)
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
if (result.code == 2005) {
this.loginVisible = true;
}
return this.$message.error(response.data.message);
}
this.records = result.data.records;
this.total = result.data.total;
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
},
handleCurrentChange(val) {
this.searchList(val)
},
login() {
axios.post('/recharge/login', this.loginer)
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
return this.$message.error(response.data.message);
}
window.sessionStorage.setItem('token', result.data.token)
this.loginVisible = false;
this.$message.success('登录成功');
this.searchList(1);
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
}
}
})
</script>
</html>
Loading…
Cancel
Save