efps-version
elf 1 year ago
parent ee5a53e7bc
commit e0bdc9f2ea

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Command;
use App\Helper\Efps\Api;
use App\Helper\Efps\Signer;
use App\Helper\StringHelper;
use App\Request\BindCardRequest;
use App\Request\PaymentQueryRequest;
@ -43,6 +44,24 @@ class MineCommand extends HyperfCommand
public function handle(): void
{
/**
* @var PaymentService $paymentService
*/
$paymentService = $this->container->make(PaymentService::class);
$params = $this->pay();
$data = $paymentService->payment($params);
var_dump($data);
return;
$data = '{"amount":100,"procedureFee":0,"payerInfo":{"bankCode":"ICBC","cardType":"D","payerName":"饶丽秀","cardNo":"621226*********9613"},"payTime":"20230608205458","outTradeNo":"2023060820542300001","transactionNo":"32202306080424492842514","cashAmount":100,"customerCode":"562276004021027","payState":"00","payerAmount":100,"channelOrder":"2023060809159764121176190110008","nonceStr":"78bbeb2da77943b5845f861110048ad6"}';
$str = 'a:1:{i:0;s:344:"ZLtxw/cBTFE+PDyxcfS+/amMMaReCPGAPS88UOEYZG4vv3ekwYDzeHOXo9yIBaaRCo98FeER+3AdFH/KNUXkcLPZPLqezFlolxfBCPoVIUk6R0d6TLMgCXYYDDUVq8OQ2na/qQYxib2eDVJtJjyxrr2HKqaCS9ZrXUIFtYeV+/o3CmtY/P4mn3sEwjaiVYOXhsmgQ8v/gW3L+Z/ba7jmDdGXTc/Fc8Uyfzh4sTzafyiqWnCRSD5dY838BzjIZKiqwBH2wKywpnEdAiqXKqjDxHac9dx4xFenxGNPxQN1wi7eKn/DHrSwV6ATuQcuEh0c5EGnGOfeEMcOJ2oroNpdgA==";}';
$data = '{"amount":5000,"procedureFee":23,"payerInfo":{"bankCode":"ICBC","cardType":"D","payerName":"\u9c8d\u4e91\u8f89","cardNo":"621226*********3143"},"payTime":"20230610180818","outTradeNo":"2023061018080300001","transactionNo":"32202306102881341174762","cashAmount":5000,"customerCode":"562276004021027","payState":"00","payerAmount":5000,"channelOrder":"2023061016326911986931600110901","nonceStr":"bda108e1ed1947f488be4b3b23bb6562"}';
$data = '{"amount":5000,"procedureFee":23,"payerInfo":{"bankCode":"ICBC","cardType":"D","payerName":"\u9c8d\u4e91\u8f89","cardNo":"621226*********3143"},"payTime":"20230610180818","outTradeNo":"2023061018080300001","transactionNo":"32202306102881341174762","cashAmount":5000,"customerCode":"562276004021027","payState":"00","payerAmount":5000,"channelOrder":"2023061016326911986931600110901","nonceStr":"bda108e1ed1947f488be4b3b23bb6562"}';
$data = '{"amount":5000,"procedureFee":23,"payerInfo":{"bankCode":"ICBC","cardType":"D","payerName":"鲍云辉","cardNo":"621226*********3143"},"payTime":"20230610180818","outTradeNo":"2023061018080300001","transactionNo":"32202306102881341174762","cashAmount":5000,"customerCode":"562276004021027","payState":"00","payerAmount":5000,"channelOrder":"2023061016326911986931600110901","nonceStr":"bda108e1ed1947f488be4b3b23bb6562"}';
$str = 'a:1:{i:0;s:344:"KKfrhc/4YNJFuphVMe8yo4sT+gQakxNtOfMqSqSeeMAHMp6684jm76p2yRog9pv7UE5WLJ8EEWajEMfLKYSBYIG9c2L3CPp+aJ+ot39SrAbq3BzCTiQvxC7Om6I7pOewU5m+ZVrlL/kLapi6lShx1vzZnGDzjJ0s+QFdY7sfm7NmqEgyZn1Q0L6IguT4/TmM0GNsB4XhO0IozXEa1EYzI//bS2eRtCLGh2TCND+4+mhdaBPsjD3F0g9C7hDU0cLPqOBd1Rzl22F0W8R0u5DzOp2ic4pdjVoWr7HV9ZS3nsnKANktLFQNSaQ3oH/dXyeY9kTfadKymPvDXavgCCmc/Q==";}';
var_dump(unserialize($str));
var_dump(Signer::verify($data, unserialize($str)[0]));
return;
// $ret = Api::withdrawalToCard([]);
// var_dump($ret);
// return;
@ -227,4 +246,21 @@ class MineCommand extends HyperfCommand
$params = $request->getData();
var_dump($params);
}
public function pay()
{
$params = [
'app_id' => '202304270000004',
'timestamp' => time(),
'nonce_str' => StringHelper::getRandomString(32),
'data' => json_encode([
'outOrderNo' => time().rand(1000, 9999),
'outMemberId' => 'T001',
'notifyUrl' => 'https://www.baidu.com',
]),
];
$sign = \App\Helper\Platform\Signer::sign($params, 'lSHKbuFngCXHN8Ue1s8QHAAzPvOL3u9O');
$params['sign'] = $sign;
return $params;
}
}

@ -40,10 +40,10 @@ class NotifyController extends AbstractController
];
}
$params = json_decode($data, true);
$outOrderNo = $params['outTradeNo'] ?: '';
$order = Order::where('out_order_no', $outOrderNo)->first();
$outTradeNo = $params['outTradeNo'] ?: '';
$order = Order::where('order_no', $outTradeNo)->first();
if (!$order) {
Log::info('paymentNotifyToOut: ' . '订单号不存在[' . $outOrderNo . ']');
Log::info('paymentNotifyToOut: ' . '订单号不存在[' . $outTradeNo . ']');
return [
'returnCode' => '0000',
'returnMsg' => '处理成功'
@ -51,7 +51,7 @@ class NotifyController extends AbstractController
}
$app = App::where('app_id', $order->app_id)->first();
if (!$app) {
Log::info('paymentNotifyToOut: ' . 'APP不存在[' . $outOrderNo . '][' . $order->app_id . ']');
Log::info('paymentNotifyToOut: ' . 'APP不存在[' . $outTradeNo . '][' . $order->app_id . ']');
return [
'returnCode' => '0000',
'returnMsg' => '处理成功'
@ -70,12 +70,12 @@ class NotifyController extends AbstractController
$this->paymentService->handlePayResult($result, $order);
$result = $this->notify($order->notify_url, $app, [
'outTradeNo' => $params['outTradeNo'] ?: '',
'transactionNo' => $params['transactionNo'] ?: '',
'outOrderNo' => $order->out_order_no ?: '',
'orderNo' => $params['outTradeNo'] ?: '',
'payState' => $params['payState'],
'amount' => $params['amount'] ?: 0,
]);
Log::info('paymentNotifyToOut result: ' . '订单[' . $outOrderNo . '][' . $$result . ']');
Log::info('paymentNotifyToOut result: ' . '订单[' . $outTradeNo . '][' . $$result . ']');
return [
'returnCode' => '0000',

@ -26,22 +26,26 @@ class RechargeController extends AbstractController
}
public function getMemberInfo(RequestInterface $request) {
[$app, $prePayLog] = $this->checkToken($request->input('token', ''));
[$app, $prePayLog] = $this->checkToken($request->input('stoken', ''));
$user = User::where('out_member_id', $prePayLog->out_member_id)->first();
$bankCard = null;
$userInfo = null;
if ($user) {
$bankCard = BankCard::where('member_id', $user->member_id)->where('status', BankCard::STATUS_ACTIVE)->first();
$userInfo = [
'name' => $user->real_name ?? '',
'cardNo' => $user->card_no ?? '',
'mobile' => $user->mobile ?? '',
'bankCardNo' => $bankCard->bank_card_no ?? '',
];
}
return $this->success([
'name' => $user->real_name ?? '',
'card_no' => $user->card_no ?? '',
'mobile' => $user->mobile ?? '',
'bank_card_no' => $bankCard->bank_card_no ?? '',
'user' => $userInfo
]);
}
public function recharge(RequestInterface $request) {
[$app, $prePayLog] = $this->checkToken($request->input('token', ''));
[$app, $prePayLog] = $this->checkToken($request->input('stoken', ''));
$name = $request->input('name');
if (empty($name)) {
throw new BusinessException('请输入姓名');
@ -72,13 +76,17 @@ class RechargeController extends AbstractController
$user = User::where('member_id', $memberId)->first();
$bankCard = null;
if ($user) {
if (empty($user->out_member_id)) {
$user->out_member_id = $prePayLog->out_member_id;
$user->save();
}
$bankCard = BankCard::where('member_id', $user->member_id)->where('bank_card_no', $bankCardNo)->where('status', BankCard::STATUS_ACTIVE)->first();
}
if ($bankCard) {
$outTradeNo = $prePayLog->out_order_no;
$outOrderNo = $prePayLog->out_order_no;
$nextStep = 'confirm-pay';
$bizData = $this->paymentService->protocolPayPreRequest($this->buildPrepayParams($prePayLog->out_member_id, $outTradeNo, $bankCard->protocol, intval($amount * 100), $app));
$bizData = $this->paymentService->protocolPayPreRequest($this->buildPrepayParams($prePayLog->out_member_id, $outOrderNo, $bankCard->protocol, intval($amount * 100), $app));
} else {
$mchOrderNo = StringHelper::generateBankCardOrderNo();
$nextStep = 'confirm-bind';
@ -94,7 +102,7 @@ class RechargeController extends AbstractController
}
public function confirmBindCard(RequestInterface $request) {
[$app, $prePayLog] = $this->checkToken($request->input('token', ''));
[$app, $prePayLog] = $this->checkToken($request->input('stoken', ''));
$outMemberId = $request->input('outMemberId');
$smsNo = $request->input('smsNo');
$smsCode = $request->input('smsCode');
@ -106,7 +114,7 @@ class RechargeController extends AbstractController
}
public function confirmPay(RequestInterface $request) {
[$app, $prePayLog] = $this->checkToken($request->input('token', ''));
[$app, $prePayLog] = $this->checkToken($request->input('stoken', ''));
$outMemberId = $request->input('outMemberId');
$token = $request->input('token');
$protocol = $request->input('protocol');
@ -139,7 +147,7 @@ class RechargeController extends AbstractController
return $params;
}
private function buildPrepayParams($outMemberId, $outTradeNo, $protocol, $amount, $app)
private function buildPrepayParams($outMemberId, $outOrderNo, $protocol, $amount, $app)
{
$params = [
'app_id' => $app->app_id,
@ -147,7 +155,7 @@ class RechargeController extends AbstractController
'nonce_str' => StringHelper::getRandomString(32),
'data' => json_encode([
'outMemberId' => $outMemberId,
'outTradeNo' => $outTradeNo,
'outOrderNo' => $outOrderNo,
'protocol' => $protocol,
'payAmount' => $amount,
]),
@ -195,16 +203,53 @@ class RechargeController extends AbstractController
{
$page = $request->input('page', 1);
$pageSize = $request->input('pageSize', 20);
$status = $request->input('status', 0);
$timeRange = $request->input('timeRange', null);
$token = $request->input('token');
$mobile = $request->input('mobile', '');
$cardNo = $request->input('cardNo', '');
$orderNo = $request->input('orderNo', '');
$outOrderNo = $request->input('outOrderNo', '');
$bankCardNo = $request->input('bankCardNo', '');
$value = Redis::get('token:' . $token);
$users = $this->getUsers();
if (empty($value) || !isset($users[$value])) {
$appId = Redis::get('token:' . $token);
if (empty($appId)) {
throw new UnauthorizedException();
}
$offset = ($page - 1) * $pageSize;
$orders = Order::query()->orderBy('id', 'desc')->offset($offset)->limit($pageSize)->get();
$query = Order::query()->where('app_id', $appId);
if ($status) {
$query->where('status', $status);
}
if ($mobile) {
$memberIds = User::where('app_id', $appId)->where('mobile', $mobile)->get(['member_id'])->pluck('member_id')->toArray();
$query->whereIn('member_id', $memberIds);
}
if ($cardNo) {
$memberIds = User::where('app_id', $appId)->where('card_no', $cardNo)->get(['member_id'])->pluck('member_id')->toArray();
$query->whereIn('member_id', $memberIds);
}
if ($bankCardNo) {
$protocols = BankCard::where('app_id', $appId)->where('bank_card_no', $bankCardNo)->get(['protocol'])->pluck('protocol')->toArray();
$query->whereIn('protocol', $protocols);
}
if ($orderNo) {
$query->where('order_no', $orderNo);
}
if ($outOrderNo) {
$query->where('out_order_no', $outOrderNo);
}
if ($timeRange) {
$timeRange[0] .= ' 00:00:00';
$timeRange[1] .= ' 23:59:59';
$query->whereBetween('created_at', $timeRange);
}
$countQuery = clone $query;
$sumQuery = clone $query;
$orders = $query->orderBy('id', 'desc')->offset($offset)->limit($pageSize)->get();
$protocols = $orders->pluck('protocol');
$bankCards = BankCard::whereIn('protocol', $protocols)->get();
$bankCards = $bankCards->keyBy('protocol');
@ -225,10 +270,12 @@ class RechargeController extends AbstractController
];
}
$total = Order::query()->count();
$total = $countQuery->count();
$amount = $sumQuery->sum('amount');
return $this->success([
'records' => $records,
'total' => $total,
'amount' => $amount / 100,
]);
}
@ -241,28 +288,31 @@ class RechargeController extends AbstractController
throw new BusinessException('账号或密码错误');
}
$users = $this->getUsers();
$user = $this->getUser($username);
if (!$user) {
throw new BusinessException('账号或密码错误');
}
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]);
if ($user['password'] !== $password) {
throw new BusinessException('账号或密码错误');
}
throw new BusinessException('账号或密码错误');
$token = md5(microtime() . $username . $password);
Redis::set('token:' . $token, $user['app_id']);
Redis::expire('token:' . $token, 60*60);
return $this->success(['token' => $token]);
}
private function getUsers() {
return [
'owx0tlx' => 'lSoLW28NxtMlxUazC8p',
'ioexlp2' => 'wwU8Ir3Xp0rxXssA9NV'
private function getUser($username) {
$users = [
'owx0tlx' => ['password' => 'lSoLW28NxtMlxUazC8p', 'app_id' => '202304270000004'],
'ioexlp2' => ['password' => 'wwU8Ir3Xp0rxXssA9NV', 'app_id' => '202305270000001'],
'lix73nxIN' => ['password' => 'a01@lWl3dfNmT', 'app_id' => '202306140000001'],
];
return $users[$username] ?? null;
}
private function checkToken($token) {
$app = App::query()->orderBy('id', 'asc')->first();
return $app;
if (empty($token)) {
throw new BusinessException('token异常');
}
@ -273,10 +323,6 @@ class RechargeController extends AbstractController
if ($log->created_at->timestamp < time() - 5*60) {
throw new BusinessException('支付超时,请重新请求');
}
$order = Order::where('app_id', $log->app_id)->where('out_order_no', $log->out_order_no)->first();
if ($order) {
throw new BusinessException('订单重复,请重新请求');
}
$app = App::where('app_id', $log->app_id)->first();
if (empty($app)) {
throw new BusinessException('应用异常');

@ -35,10 +35,10 @@ class PaymentService extends AbstractService
public function createOrder(App $app, array $params, $user) {
$order = new Order();
$order->app_id = $app->app_id;
$order->order_no = StringHelper::generateOrderNo();
$order->order_no = $params['outTradeNo'];
$order->member_id = $user->member_id;
$order->out_member_id = $params['outMemberId'] ?? '';
$order->out_order_no = $params['outTradeNo'] ?? '';
$order->out_order_no = $params['outOrderNo'] ?? '';
$order->amount = $params['payAmount'] ?? 0;
$order->notify_url = $params['notifyUrl'] ?? '';
$order->order_info = json_encode($params['orderInfo'] ?? [], JSON_UNESCAPED_UNICODE);
@ -82,6 +82,17 @@ class PaymentService extends AbstractService
$req = new ProtocolPayPreRequest($params);
$app = $req->getApp();
$data = $req->getData();
if ($data['payAmount'] > 3000) {
throw new BusinessException('超出限额');
}
$order = Order::where('app_id', $app->app_id)->where('out_order_no', $data['outOrderNo'])->first();
if ($order) {
throw new BusinessException('订单重复');
}
$data['outTradeNo'] = StringHelper::generateOrderNo();
$result = Api::protocolPayPre($data);
$user = User::where('app_id', $app->app_id)->where('out_member_id', $data['outMemberId'])->first();

@ -21,6 +21,7 @@ Router::addGroup('/payment',function () {
Router::post('/protocol-pay-confirm', [PayController::class, 'protocolPayConfirm']);
Router::post('/refund-query', [PayController::class, 'refundQuery']);
Router::post('/payment-query', [PayController::class, 'paymentQuery']);
Router::post('/pay', [PayController::class, 'payment']);
}, ['middleware' => [\App\Middleware\RequestLogMiddleware::class]]);
Router::addGroup('/recharge',function () {
@ -29,6 +30,7 @@ Router::addGroup('/recharge',function () {
Router::post('/confirm-pay', [RechargeController::class, 'confirmPay']);
Router::post('/orders', [RechargeController::class, 'orders']);
Router::post('/login', [RechargeController::class, 'login']);
Router::post('/get-member-info', [RechargeController::class, 'getMemberInfo']);
});
Router::addGroup('/notify',function () {

@ -127,4 +127,6 @@ CREATE TABLE `pre_pay_logs` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='预支付表';
alter table users add column `out_member_id` varchar(32) not null default '' after member_id;
alter table orders add column `out_member_id` varchar(32) not null default '' after member_id;
alter table orders add column `out_member_id` varchar(32) not null default '' after member_id;
alter table orders add column `member_id` varchar(32) not null default '' after app_id;
alter table orders add column `order_no` varchar(32) not null default '' after app_id;

@ -11,6 +11,49 @@
<el-container>
<el-header style="text-align: center;">充值记录</el-header>
<el-main>
<el-row>
<el-form :inline="true" :model="search">
<el-form-item label="">
<el-input v-model="search.outOrderNo" placeholder="商户订单号" clearable></el-input>
</el-form-item>
<el-form-item label="">
<el-input v-model="search.orderNo" placeholder="支付订单号" clearable></el-input>
</el-form-item>
<el-form-item label="">
<el-input v-model="search.cardNo" placeholder="身份证号" clearable></el-input>
</el-form-item>
<el-form-item label="">
<el-input v-model="search.mobile" placeholder="手机号" clearable></el-input>
</el-form-item>
<el-form-item label="">
<el-input v-model="search.bankCardNo" placeholder="银行卡号" clearable></el-input>
</el-form-item>
<el-form-item label="">
<el-date-picker
v-model="search.timeRange"
type="daterange"
value-format="yyyy-MM-dd"
range-separator="至"
start-placeholder="支付开始日期"
end-placeholder="支付结束日期">
</el-date-picker>
</el-form-item>
<el-form-item label="">
<el-select v-model="search.status" placeholder="支付状态" clearable>
<el-option label="支付成功" value="6"></el-option>
<el-option label="支付失败" value="9"></el-option>
<el-option label="待支付" value="2"></el-option>
<el-option label="申请失败" value="3"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="query">查询</el-button>
</el-form-item>
<el-form-item>
<div style="line-height: 20px; margin-left: 20px; display: inline-block; margin-top: 10px; font-size: 14px;">充值金额:{{ amount }}</div>
</el-form-item>
</el-form>
</el-row>
<el-row>
<el-col :span="24">
<el-table
@ -56,7 +99,8 @@
layout="prev, pager, next"
@current-change="handleCurrentChange"
:page-size="pageSize"
:total="total">
:total="total"
style="margin-top: 10px">
</el-pagination>
</el-col>
</el-row>
@ -88,8 +132,19 @@
el: '#app',
data() {
return {
search: {
name: '',
mobile: '',
cardNo: '',
bankCardNo: '',
orderNo: '',
outOrderNo: '',
timeRange: null,
status: undefined
},
records: [],
total: 0,
amount: 0,
pageSize: 20,
loginVisible: false,
loginer: {
@ -107,11 +162,10 @@
},
methods: {
searchList(page) {
let data = {
token: window.sessionStorage.getItem('token'),
page: page,
pageSize: this.pageSize
}
let data = {...this.search}
data.token = window.sessionStorage.getItem('token');
data.page = page;
data.pageSize = this.pageSize;
axios.post('/recharge/orders', data)
.then( (response) => {
console.log(response);
@ -124,6 +178,7 @@
}
this.records = result.data.records;
this.total = result.data.total;
this.amount = result.data.amount;
})
.catch((error) => {
this.$message.error('请求错误');
@ -131,6 +186,9 @@
});
console.log('submit!');
},
query() {
this.searchList(1)
},
handleCurrentChange(val) {
this.searchList(val)
},

@ -27,7 +27,7 @@
<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-input-number v-model="form.amount" :min="1" :max="3000" label="充值金额"></el-input-number>
</el-form-item>
<el-form-item label="备注">
<el-input type="textarea" v-model="form.remark"></el-input>
@ -74,21 +74,24 @@
el: '#app',
data() {
return {
token: undefined,
stoken: undefined,
bindConfirmVisible: false,
bindConfirmForm: {
stoken: '',
smsCode: '',
smsNo: '',
memberId: ''
},
payConfirmVisible: false,
payConfirmForm: {
stoken: '',
smsCode: '',
memberId: '',
token: '',
protocol: ''
},
form: {
stoken: '',
name: '',
mobile: '',
cardNo: '',
@ -99,10 +102,14 @@
}
},
created() {
this.token = this.getQueryParam('token');
if (!this.token) {
this.stoken = this.getQueryParam('token');
if (!this.stoken) {
return this.$message.error('参数异常');
}
this.form.stoken = this.stoken;
this.bindConfirmForm.stoken = this.stoken;
this.payConfirmForm.stoken = this.stoken;
this.getMemberInfo()
},
methods: {
recharge() {
@ -171,16 +178,39 @@
});
console.log('submit!');
},
getQueryParam($name) {
getQueryParam(name) {
var query = window.location.search.substring(1);
console.log(query)
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
console.log(pair[0], name)
if(pair[0] == name) {
return pair[1];
}
}
return undefined;
},
getMemberInfo() {
axios.post('/recharge/get-member-info', {stoken: this.stoken})
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
return this.$message.error(response.data.message);
}
if (result.user != null) {
this.form.name = result.user.name;
this.form.cardNo = result.user.cardNo;
this.form.mobile = result.user.mobile;
this.form.bankCardNo = result.user.bankCardNo;
}
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
}
}
})

Loading…
Cancel
Save