Compare commits

...

83 Commits
master ... dev

Author SHA1 Message Date
elf ff4bac896e y 1 year ago
elf 033b9a1250 y 1 year ago
elf 95fe6d2432 y 1 year ago
elf 0207b97b81 yh 1 year ago
elf 3d13c63463 yh 1 year ago
elf 6e4e5c5973 yh 1 year ago
ljl a3cf428367 yh 1 year ago
ljl a7056cf6be yh 1 year ago
ljl db16e2f0f2 yh 1 year ago
ljl cb6c2c5cb0 yh 1 year ago
ljl 3e1fbd3e53 yh 1 year ago
ljl b665ef7bd7 yh 1 year ago
ljl 4733abea24 yh 1 year ago
ljl ee37a6bded yh 1 year ago
ljl 5c724cee4b yh 1 year ago
ljl 61821ed298 yh 1 year ago
ljl 8cbf20d459 yh 1 year ago
ljl 804aff95dc yh 1 year ago
ljl 95b9b5ea9e 修改bug 1 year ago
elf 447d9eb1ad yh 1 year ago
ljl f082399caf yh 1 year ago
ljl 1e13a50ce0 yh 1 year ago
elf 0faba2c5b7 yx 1 year ago
ljl 7c6993473d yh 1 year ago
ljl 2558522c77 yh 1 year ago
ljl 4c483fc063 yh 1 year ago
ljl fcc595d278 yh 1 year ago
ljl 769ce6e86c yh 1 year ago
elf 7b22609ca9 yh 1 year ago
elf 9d6e45a7bb yh 1 year ago
elf 97ee40f741 yh 1 year ago
elf 162ec2b0e2 yh 1 year ago
elf 663471ca39 yh 1 year ago
elf 2408adec7c yh 1 year ago
elf f833716f17 yh 1 year ago
elf 4194e37197 yh 1 year ago
elf 248d9c15cc yh 1 year ago
elf 66e1db494f yh 1 year ago
elf c82dfaaf98 yh 1 year ago
elf 206d11c81b yh 1 year ago
elf 6f34aae8d2 yh 1 year ago
ljl d69dcdb6ac yh 1 year ago
ljl a9d28b2b2d yh 1 year ago
ljl 5edcd1a8ee yh 1 year ago
ljl 0a6b99f303 yh 1 year ago
ljl 5235785698 yh 1 year ago
ljl 0041d00565 yh 1 year ago
ljl 59c29044df yh 1 year ago
ljl 9368d22567 yh 1 year ago
ljl 8cea033e0a yh 1 year ago
ljl 9b1455ced7 yh 1 year ago
ljl 0223f71f93 yh 1 year ago
ljl 7d8b76f9f4 yh 1 year ago
ljl 6f2ffe971c yh 1 year ago
ljl 00ecb241e2 yh 1 year ago
elf 17eef6737f yh 1 year ago
ljl 5a4bedc366 yh 1 year ago
ljl 0724bebaa2 yh 1 year ago
ljl 7ec313819e yh 1 year ago
ljl b54548d509 yh 1 year ago
ljl 518d3bf7c6 yh 1 year ago
ljl 4577a9492a yh 1 year ago
ljl 5143e96d14 yh 1 year ago
ljl 2bc2f6115e yh 1 year ago
ljl 9254532fa6 yh 1 year ago
ljl 6d34a1da92 yh 1 year ago
ljl cabc1f14a2 yh 1 year ago
ljl 0b3c9be6b6 yh 1 year ago
ljl 39a6908392 yh 1 year ago
ljl bab630b15a yh 1 year ago
ljl 0427d515e6 yh 1 year ago
ljl 7395d2a785 yh 1 year ago
ljl 907f66c8e7 yh 1 year ago
ljl aced4299f7 yh 1 year ago
ljl ab56ca6fbb yh 1 year ago
elf 635048a6ae yh 1 year ago
elf 9651a08abf yh 1 year ago
elf abbebe6ca2 yh 1 year ago
elf 4c7d99a894 yh 1 year ago
elf 4d1b34bf26 yh 1 year ago
elf 6c2a3e0c6f yh 1 year ago
elf 63cd600172 yh 1 year ago
elf 4022901c65 yh 1 year ago

@ -4,11 +4,14 @@ declare(strict_types=1);
namespace App\Command;
use App\Helper\Baofu\Baofu;
use App\Helper\Log;
use App\Helper\Platform\Notification;
use App\Helper\Platform\Signer;
use App\Helper\StringHelper;
use App\Model\App;
use App\Model\BankCard;
use App\Model\User;
use App\Service\AppService;
use App\Service\MerchantService;
use App\Service\PaymentService;
@ -45,8 +48,17 @@ class MineCommand extends HyperfCommand
public function handle(): void
{
// $this->rsyncBankCards();
// return;
$this->withdraw();
// $this->transferWithdrawNotify();
$this->getBalance();
return;
$this->querySignEntrust();
return;
$this->getBalance();
$this->getRequestData();
return;
// $this->notify('http://ceshi-shop.hkcpex.com/index.php/pay/notify/baofu_f_register', $this->getApp(), ['userId' => '30684']);
$this->notify('http://ceshi-shop.hkcpex.com/index.php/pay/notify/baofu_f_bind_card', $this->getApp(), ['userId' => '23121', 'bindCardFlag' => true]);
return;
@ -99,14 +111,92 @@ class MineCommand extends HyperfCommand
protected function getRequestData() {
$app = $this->getApp();
$data = json_encode([
'userId' => 'CWX1989'
]);
$data = [
'userId' => 'ELF1990',
'goodsName' => '测试商品',
'agreementNo' => '312023082200002060225',
'notifyUrl' => 'http://124.223.222.61:9501/notify/test-notify',
'returnUrl' => 'http://124.223.222.61:9501/notify/test-notify',
'amount' => 100,
'outOrderNo' => time() . rand(1000, 9999),
'validDate' => '2023-08-15',
'marketInfo' => [
'amount' => 0,
'remark' => 'test',
],
'splitInfoList' => [
[
'splitUserId' => 'RLX1990',
'sellerFlag' => 1,
'splitAmount' => 100,
'subOutOrderNo' => time() . rand(1000, 9999),
]
]
];
$data = [
'userId' => 'ELF1990',
'oldOutOrderNo' => '16926878308874',
'outOrderNo' => time() . rand(1000, 9999),
'amount' => '100',
'notifyUrl' => 'http://124.223.222.61:9501/notify/test-notify',
'assureConfirmSplitInfoList' => [
[
'oldSubOutOrderNo' => '16926878304208',
'splitAmount' => '100',
]
],
];
$data = [
'userId' => 'ELF1990',
'accountName' => '廖金灵',
'outApplyNo' => time() . rand(1000, 9999),
'amount' => '10',
'summary' => '测试',
'notifyUrl' => 'http://124.223.222.61:9501/notify/test-notify'
];
// $data = [
// 'userId' => 'ELF1990',
// 'agreementNo' => '312023082200002060225',
// 'outWithdrawNo' => time() . rand(1000, 9999),
// 'amount' => '1',
// 'notifyUrl' => 'http://124.223.222.61:9501/notify/test-notify',
// 'returnUrl' => 'https://www.baidu.com',
// ];
// $data = [
// 'userId' => 'ELF1990',
// 'outApplyNo' => '16934203547527',
// ];
// $data = [
// 'type' => 'WITHDRAW',
// 'outOrderNo' => '16934198607215',
// ];
$data = [
'userId' => 'ELF1990',
'agreementNo' => '312023081500002054664',
'outOrderNo' => time() . rand(1000, 9999),
'amount' => 10,
'goodsName' => '测试商品',
'payMethod' => 'unionPay',
'payType' => 'ALIPAY_ALXCX',
'notifyUrl' => 'http://124.223.222.61:9501/notify/test-notify',
'returnUrl' => 'http://124.223.222.61:9501/notify/test-notify',
'channelId' => '20880055945509133097978700117397',
'appId' => '2021004111671035',
// 'validDate' => '2023-09-30',
'splitInfoList' => [
[
'splitUserId' => 'RLX1990',
'sellerFlag' => 1,
'splitAmount' => 10,
'subOutOrderNo' => time() . rand(1000, 9999),
]
]
];
$params = [
'app_id' => $app->app_id,
'nonce_str' => StringHelper::getRandomString(16),
'timestamp' => time(),
'data' => $data,
'data' => json_encode($data),
];
$params['sign'] = Signer::sign($params, $app->app_key);
echo json_encode($params);
@ -145,7 +235,7 @@ class MineCommand extends HyperfCommand
* @var UserService $userService
*/
$userService = $this->container->make(UserService::class);
$userService->rsyncBankCards('4673f922e30cfd2efeeb992ff6a32ece');
$userService->rsyncBankCards('f27f7786068387029a126de736bb84b2');
}
protected function bindCard()
@ -154,7 +244,7 @@ class MineCommand extends HyperfCommand
* @var UserService $userService
*/
$userService = $this->container->make(UserService::class);
$url = $userService->bindCard(['userId' => 'ELF1990'], $this->getApp(), $this->getToken());
$url = $userService->bindCard(['userId' => 'CWX1989'], $this->getApp(), $this->getToken());
echo $url;
}
@ -164,7 +254,7 @@ class MineCommand extends HyperfCommand
* @var UserService $userService
*/
$userService = $this->container->make(UserService::class);
$result = $userService->unbindCard(['userId' => 'ELF1990', 'agreementNo' => '312023080400002047764'], $this->getApp());
$result = $userService->unbindCard(['userId' => 'ELF1990', 'agreementNo' => '312023081200002052866'], $this->getApp());
var_dump($result);
}
@ -307,7 +397,7 @@ class MineCommand extends HyperfCommand
$data = [
'userId' => 'ELF1990',
'goodsName' => '测试商品',
'agreementNo' => '312023081200002052866',
'agreementNo' => '312023082200002060225',
'notifyUrl' => 'http://www.baidu.com',
'returnUrl' => 'http://www.baidu.com',
'amount' => 100,
@ -329,4 +419,174 @@ class MineCommand extends HyperfCommand
$result = $paymentService->transferPay($data, $this->getApp(), $this->getToken());
var_dump($result);
}
protected function unionPay()
{
/**
* @var PaymentService $paymentService
*/
$paymentService = $this->container->make(PaymentService::class);
$data = [
'userId' => 'ELF1990',
'goodsName' => '测试商品',
'agreementNo' => '312023081200002052866',
'notifyUrl' => 'http://www.baidu.com',
'returnUrl' => 'http://www.baidu.com',
'amount' => 100,
'outOrderNo' => time() . rand(1000, 9999),
'validDate' => '2023-08-15',
'payMethod' => 'unionPay',
'payType' => 'ALIPAY_NATIVE',
'splitInfoList' => [
[
'splitUserId' => 'RLX1990',
'sellerFlag' => 1,
'splitAmount' => 100,
'subOutOrderNo' => time() . rand(1000, 9999),
]
]
];
$result = $paymentService->payment($data, $this->getApp(), $this->getToken());
var_dump($result);
}
public function queryOrder()
{
/**
* @var PaymentService $paymentService
*/
$paymentService = $this->container->make(PaymentService::class);
$data = [
'outOrderNo' => '16926878308874',
];
$order = $paymentService->queryOrder($data, $this->getApp());
var_dump($order->toArray());
}
public function paymentNotify() {
/**
* @var PaymentService $paymentService
*/
$paymentService = $this->container->make(PaymentService::class);
/**
* @var RequestService $requestService
*/
$requestService = $this->container->make(RequestService::class);
$params = json_decode('{"orgNo":"1274207","merchantNo":"1274207","terminalNo":"82254","orderStatus":"FINISH","tradeId":"2023082115523700001","paidType":"","orderMoney":"100","loginId":"1f32d22ff571ebc692bd50785c883ca8","finishTime":"20230821155509","orderId":"23082100711351457","errorMsg":"成功","signature":"c369c2670607f4e840d7a9644e854da9b1858aa9df1c465fa893b8a9610bde561704fe8f63af41cb1528f601a6fafcbb42ec7fa4838cdc76dc86593ae0c60ae15bae227e60a82ce376a4a7c137047f3db0bb366c21e484458abed0bb9135b653948f90b7d0b4c89d29e0b1939915c80d49c6e6cc0549a1eb84fb2c14704d81fd"}', true);
$token = 'f49e9fc5bf6f4768fb47a5721ede7d47';
$baofu = new Baofu();
if (!$baofu->notifyVerify($params, 'payment')) {
Log::info('paymentNotifyVerifyFail: ', $params);
return $baofu->notifySuccess();
}
$requestLog = $requestService->getRequestLogByToken($token);
$info = [
'member_id' => $params['loginId'],
'order_no' => $params['tradeId'],
'third_order_no' => $params['orderId'],
'status' => $params['orderStatus'],
'amount' => $params['orderMoney'],
'finished_at' => $params['finishTime'],
'error_message' => $params['errorMsg'],
'transaction_id' => $params['transactionId'] ?? '',
'out_transaction_id' => $params['outTransactionId'] ?? '',
];
$order = $paymentService->updateOrder($info, ['APPLY_SUCCESS', 'PROCESS', 'CONFIRM_SUCCESS']);
if (empty($order)) {
return $baofu->notifySuccess();
}
$result = $this->notify(
$requestLog->getDataValue('notifyUrl'),
$requestLog->app,
[
'amount' => $order->amount,
'status' => $order->status,
'userId' => $order->user_id,
'orderNo' => $order->order_no,
'outOrderNo' => $order->out_order_no,
'finishTime' => $order->finished_at,
]
);
$baofu->notifySuccess();
}
public function transferWithdraw() {
$baofu = new Baofu();
$data = [
'transContent' => [
[
'transNo' => time() . rand(1000, 9999),
'transMoney' => 0.1,
'transType' => 2,
'transAccNo' => '3177000500533754',
'transAccName' => '廖金灵',
'transSummary' => '测试',
// 'cardBankName' => '',
// 'cardProName' => '',
// 'cardCityName' => '',
// 'cardAccDept' => '',
// 'cardCnap' => '',
// 'transIdCard' => '',
// 'transMobile' => '',
]
]
];
$baofu->transferWithdraw($data);
}
protected function unbindWithdrawEntrust($userId = 'ELF1990') {
/**
* @var UserService $userService
*/
$userService = $this->container->make(UserService::class);
$url = $userService->unbindWithdrawEntrust(['userId' => $userId], $this->getApp(), $this->getToken());
echo $url;
}
protected function signWithdrawEntrust($userId = 'ELF1990') {
/**
* @var UserService $userService
*/
$userService = $this->container->make(UserService::class);
$url = $userService->signWithdrawEntrust(['userId' => $userId], $this->getApp(), $this->getToken());
echo $url;
}
protected function querySignEntrust($userId = 'ELF1990') {
/**
* @var UserService $userService
*/
$userService = $this->container->make(UserService::class);
$url = $userService->querySignEntrust(['userId' => $userId], $this->getApp(), $this->getToken());
echo $url;
}
protected function transferWithdrawNotify()
{
$data = '{"member_id":"1274207","terminal_id":"82254","data_type":"json","data_content":"54902c7f11a5d1f151ee7a8f014dfa61fa35908dcbf9f763df0ac4ebde99a58208c5dd82b53b84b9387ba230accafa11540ddbed70bec1c18a3c9692338ab618e940553b77136ae08a168df767a2a4467cc20cc88ceac9676e83b6536a052df84aa24af87965f694699a569ad9f931c8f50c14bbd6b8f1a4eb8dbbe06f362a648e256a3fd4d558771f85148d62fb3099845571dbfbcdbb0e44b2b58316d25ef5cf17b02be2c1f509e592b0d32c7911a4b63974b0fc8f2b5ca216c905aeb9d81a95982fe00d1bf6e9e2251e58976dd54856b0001c1b6745532a0df5cd0a6cb72d686b43b1aa6dec349206592b5da833ed2f0d6f858661c3679e0cc7ca6fb15abdcab53548beb12ab46991efe02dcad6d27f80ef5f1523540db4a6076cc5bec6dce2ee4aa625d3e7fef47d6cd1345e660b78b078395e000ce23c8c8e8a6f921a9c0622e73e6ccb18b4143ecc7529a7d40ef707024282a40e4d49c4f1d237acf17e02cf255ad5fa033739f9fdf40e23f86ee0b79507fd7d2a02b602fbedf0579af63fc3115525b2b7c645cd81ed84e20dd866dec67446850fa65c16134a0a1c3f3b90d89564a6a794b21102c70a9e8e44f8929fdb19f6f59694bc359afe27fca758f8af272bb4ebd7e7ed49125d26608947b60330f46c4bd4b9e373967e59b6e353808b4a6fe62db53fc71312298df312b4695f79a22d3dc9f22f639bfad0a3f7dd"}';
$data = json_decode($data, true);
$baofu = new Baofu();
$content = $baofu->decryptUnionPayData($data['data_content']);
var_dump($content);
$result = json_decode($content, true);
var_dump($result);
}
protected function withdraw() {
$bankCard = BankCard::where('member_id', 'f27f7786068387029a126de736bb84b2')->first();
$baofu = new Baofu();
$result = $baofu->withdraw([
'amount' => intval(726687),
'loginNo' => 'f27f7786068387029a126de736bb84b2',
'agreementNo' => $bankCard->agreement_no,
'outOrderNo' => time() . rand(1000, 9999),
], 'elf');
var_dump($result);
}
}

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Controller\Payment;
use App\Helper\Baofu\Baofu;
use App\Helper\Baofu\Rsa;
use App\Helper\Log;
use App\Helper\Platform\Notification;
use App\Helper\Platform\Signer as PlatformSigner;
@ -64,7 +65,7 @@ class NotifyController extends AbstractController
$baofu = new Baofu();
if (!$baofu->notifyVerify($params, 'card-bind')) {
Log::info('bindCardNotifyVerifyFail: ' . $params);
Log::info('bindCardNotifyVerifyFail: ', $params);
return $baofu->notifySuccess();
}
@ -93,7 +94,7 @@ class NotifyController extends AbstractController
$baofu = new Baofu();
if (!$baofu->notifyVerify($params, 'payment')) {
Log::info('paymentNotifyVerifyFail: ' . $params);
Log::info('paymentNotifyVerifyFail: ', $params);
return $baofu->notifySuccess();
}
@ -110,7 +111,48 @@ class NotifyController extends AbstractController
'transaction_id' => $params['transactionId'] ?? '',
'out_transaction_id' => $params['outTransactionId'] ?? '',
];
$order = $this->paymentService->updateOrder($info);
$order = $this->paymentService->updateOrder($info, ['APPLY_SUCCESS', 'PROCESS', 'CONFIRM_SUCCESS']);
if (empty($order)) {
return $baofu->notifySuccess();
}
$result = $this->notify(
$requestLog->getDataValue('notifyUrl'),
$requestLog->app,
[
'amount' => $order->amount,
'status' => $order->status,
'userId' => $order->user_id,
'orderNo' => $order->order_no,
'outOrderNo' => $order->out_order_no,
'finishTime' => $order->finished_at,
]
);
$baofu->notifySuccess();
}
public function confirmAssurePortfolioPay(RequestInterface $request)
{
[$token, $params] = $this->getTokenAndParams($request);
$baofu = new Baofu();
if (!$baofu->notifyVerify($params, 'confirm-assure-portfolio-pay')) {
Log::info('confirmAssurePortfolioPayNotifyVerifyFail: ', $params);
return $baofu->notifySuccess();
}
$requestLog = $this->requestService->getRequestLogByToken($token);
$info = [
'member_id' => $params['loginId'],
'order_no' => $params['tradeId'],
'third_order_no' => $params['orderId'],
'status' => $params['orderStatus'],
'amount' => $params['orderMoney'],
'finished_at' => $params['finishTime'],
];
$order = $this->paymentService->updateOrder($info, ['SUCCESS']);
if (empty($order)) {
return $baofu->notifySuccess();
}
@ -137,7 +179,7 @@ class NotifyController extends AbstractController
$baofu = new Baofu();
if (!$baofu->notifyVerify($params, 'refund')) {
Log::info('refundNotifyVerifyFail: ' . $params);
Log::info('refundNotifyVerifyFail: ', $params);
return $baofu->notifySuccess();
}
@ -203,4 +245,82 @@ class NotifyController extends AbstractController
public function testNotify(RequestInterface $request) {
return $this->success(['params' => $request->all()]);
}
public function transferWithdraw(RequestInterface $request)
{
$params = $request->all();
Log::info('NOTIFY_DATA: ' . $request->getUri() . ':', $params);
$baofu = new Baofu();
$content = $baofu->decryptUnionPayData($params['data_content']);
$result = json_decode($content, true);
if (empty($result)) {
return 'fail';
}
Log::info('transferWithdrawResult: ', $result);
$apply = $this->paymentService->updateWithdrawApply($result, ['APPLY_SUCCESS']);
if (empty($apply)) {
return 'fail';
}
$result = $this->notify(
$apply->notify_url,
$apply->app,
[
'amount' => $apply->amount,
'status' => $apply->status,
'userId' => $apply->user_id,
'outApplyNo' => $apply->out_apply_no,
]
);
if ($result == 'success') {
return 'OK';
} else {
return 'fail';
}
}
public function withdraw(RequestInterface $request)
{
[$token, $params] = $this->getTokenAndParams($request);
$baofu = new Baofu();
if (!$baofu->notifyVerify($params, 'withdraw')) {
Log::info('withdrawNotifyVerifyFail: ', $params);
return $baofu->notifySuccess();
}
$requestLog = $this->requestService->getRequestLogByToken($token);
$info = [
'member_id' => $params['loginId'],
'order_no' => $params['tradeId'],
'third_order_no' => $params['orderId'],
'status' => $params['orderStatus'],
'amount' => $params['orderMoney'],
'finished_at' => $params['finishTime'],
];
$withdraw = $this->paymentService->updateWithdraw($info, ['APPLY_SUCCESS']);
if (empty($withdraw)) {
return $baofu->notifySuccess();
}
$result = $this->notify(
$requestLog->getDataValue('notifyUrl'),
$requestLog->app,
[
'amount' => $withdraw->amount,
'status' => $withdraw->status,
'userId' => $withdraw->user_id,
'outWithdrawNo' => $withdraw->out_withdraw_no,
]
);
if ($result == 'success') {
return $baofu->notifySuccess();
} else {
return 'fail';
}
}
}

@ -75,10 +75,21 @@ class PaymentController extends AbstractController
return $this->success(['url' => $url]);
}
public function getBalance(RequestInterface $request)
{
[$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class);
$user = User::where('app_id', $app->app_id)->where('user_id', $data['userId'])->first();
if (empty($user)) {
throw new BusinessException('用户不存在');
}
$result = $this->userService->getBalance($user->member_id);
return $this->success(['result' => $result]);
}
public function payment(RequestInterface $request) {
[$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class);
$url = $this->paymentService->payment($data, $app, $token);
return $this->success(['url' => $url]);
$data = $this->paymentService->payment($data, $app, $token);
return $this->success($data);
}
public function transferPay(RequestInterface $request) {
@ -87,24 +98,31 @@ class PaymentController extends AbstractController
return $this->success(['acsNo' => $acsNo]);
}
public function confirmPay(RequestInterface $request)
{
[$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class);
$result = $this->paymentService->confirmPay($data, $app, $token);
return $this->success(['result' => $result]);
}
public function refundApply(RequestInterface $request)
{
[$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class);
$data = $this->paymentService->refundApply($app, $data);
$data = $this->paymentService->refundApply($data, $app);
return $this->success($data);
}
public function refundConfirm(RequestInterface $request)
{
[$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class);
$this->paymentService->refundConfirm($app, $data, $token);
$this->paymentService->refundConfirm($data, $app, $token);
return $this->success();
}
public function refundCancel(RequestInterface $request)
{
[$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class);
$data = $this->paymentService->refundApply($app, $data);
$data = $this->paymentService->refundApply($data, $app);
return $this->success($data);
}
@ -127,7 +145,7 @@ class PaymentController extends AbstractController
if (empty($user)) {
throw new BusinessException('用户不存在');
}
$user = $this->userService->rsyncUser($user->member_id);
$user = $this->userService->rsyncUser($user->member_id, $app->app_id, $data['userId']);
$result = [
'realnameFlag' => $user->realname_flag,
'bindCardFlag' => $user->bind_bard_flag,
@ -138,4 +156,58 @@ class PaymentController extends AbstractController
];
return $this->success($result);
}
public function queryOrder(RequestInterface $request)
{
[$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class);
$order = $this->paymentService->queryOrder($data, $app);
$result = [
'finishTime' => $order->finished_at,
'amount' => $order->amount,
'status' => $order->status,
];
return $this->success($result);
}
public function withdraw(RequestInterface $request)
{
[$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class);
$url = $this->paymentService->withdraw($data, $app, $token);
return $this->success(['url' => $url]);
}
public function withdrawApply(RequestInterface $request)
{
[$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class);
$data = $this->paymentService->withdrawApply($data, $app);
return $this->success($data);
}
public function withdrawApplyQuery(RequestInterface $request)
{
[$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class);
$data = $this->paymentService->withdrawApplyQuery($data, $app);
return $this->success($data);
}
public function unbindWithdrawEntrust(RequestInterface $request)
{
[$app, $data, $token] = $this->parseReqest($request, RegisterRequest::class);
$url = $this->userService->unbindWithdrawEntrust($data, $app, $token);
return $this->success(['url' => $url]);
}
public function signWithdrawEntrust(RequestInterface $request)
{
[$app, $data, $token] = $this->parseReqest($request, RegisterRequest::class);
$url = $this->userService->signWithdrawEntrust($data, $app, $token);
return $this->success(['url' => $url]);
}
public function querySignEntrust(RequestInterface $request)
{
[$app, $data, $token] = $this->parseReqest($request, RegisterRequest::class);
$result = $this->userService->querySignEntrust($data, $app);
return $this->success(['result' => $result]);
}
}

@ -15,6 +15,11 @@ class ApiList
'url' => '/api/cust/v3.0.0/bindCard',
'signParams' => 'orgNo|merchantNo|terminalNo|loginNo|requestDate|cardNo|bankMobile',
],
'query-order' => [
'description' => '交易订单信息查询',
'url' => '/api/wallet/v3.0.0/queryOrder',
'signParams' => 'orgNo|merchantNo|terminalNo|requestDate|tradeId',
],
'bind-card-check' => [
'description' => '个人银行卡签约-确认绑卡',
'url' => '/api/cust/v3.0.0/bindCardCheck',
@ -149,6 +154,16 @@ class ApiList
'description' => '企业注册-聚合交易商户报备-v3.1版本-授权目录报备',
'url' => '/api/aggregationReport/v3.1.0/authBind',
'signParams' => 'orgNo|merchantNo|terminalNo|simId|authType|authContent'
],
'entrust-withdraw' => [
'description' => '委托提现交易',
'url' => '/api/order/v3.0.0/entrustWithdraw',
'signParams' => 'orgNo|merchantNo|terminalNo|loginNo|requestDate|outOrderNo|amount|agreementNo'
],
'find-sign-entrust-result' => [
'description' => '委托授权查询',
'url' => '/api/cust/v3.0.0/findSignEntrustResult',
'signParams' => 'orgNo|merchantNo|terminalNo|loginNo|requestDate'
]
];

@ -2,6 +2,7 @@
namespace App\Helper\Baofu;
use App\Exception\BusinessException;
use App\Helper\StringHelper;
class Baofu
@ -69,8 +70,8 @@ class Baofu
$data['loginNo'] = $params['loginNo'];
$data['agreementNo'] = Rsa::encryptByCERFile($params['agreementNo'], $this->getCerFilePath());
$data['outOrderNo'] = $params['outOrderNo'];
$data['notifyUrl'] = NotifyList::getNotifyUrl($params['notifyUrl'], $token);
return $this->withReturnUrl($this->api('withdraw', $data, $token), $token);
$data['notifyUrl'] = NotifyList::getNotifyUrl('withdraw', $token);
return $this->withReturnUrl($this->api('withdraw', $data), $token);
}
public function assurePaymentSplit($params, $token)
@ -181,14 +182,14 @@ class Baofu
return $this->api('cloud-b2c-assure-recharge', $data);
}
public function payment($params, $type = 'ASSURE_PAYMENT')
public function payment($params, $token)
{
$dataContent = [
'goodsName' => $params['goodsName'],
'amount' => $params['amount'],
'outOrderNo' => $params['outOrderNo'],
'expireDate' => date('YmdHis', time() + 15*60),
'notifyUrl' => $params['notifyUrl'],
'expireDate' => $params['expireDate'],
'notifyUrl' => NotifyList::getNotifyUrl('payment', $token),
'splitInfoList' => $params['splitInfoList'],
'paidType' => $params['paidType'],
'validDate' => date('Ymd'),
@ -199,22 +200,17 @@ class Baofu
// 1.微信支付(公众号、小程序)需填公众号授权获取微信用户openid
// 2.支付宝支付(生活号、小程序)需填生活号授权获取支付宝用户userid
// 其余时间不传
$data['chanalId'] = $params['chanalId'] ?: '';
$data['chanalId'] = $params['chanalId'] ?? '';
$data['dataContent'] = json_encode($dataContent);
// 1.微信支付(公众号、小程序)需填公众号授权获取微信的appid
// 2.支付宝支付(生活号、小程序)需填生活号授权获取支付宝的appid
// 支付宝主扫 不需要
$data['appId'] = $params['appId'] ?: '';
$data['isRaw'] = 0;
$data['callType'] = $type;
$data['callType'] = $params['callType'];
$res = base64_decode($this->api('payment', $data));
if(self::PEYMENT_PAID_TYPE[$params['paidType']]){
$res = json_decode($res, true);
if($res['body']){
return $res['body'];
}
}
return json_decode($res, true);
}
public function recharge($params, $token)
@ -255,7 +251,7 @@ class Baofu
return $this->api('confirm-assure-pay', $data);
}
public function confirmAssurePortfolioPay($params)
public function confirmAssurePortfolioPay($params, $token)
{
$dataContent = [
'amount' => $params['amount'],
@ -267,7 +263,7 @@ class Baofu
$data = [];
$data['loginNo'] = $params['loginNo'];
$data['dataContent'] = json_encode($dataContent);
$data['notifyUrl'] = $params['notifyUrl'];
$data['notifyUrl'] = NotifyList::getNotifyUrl('confirm-assure-portfolio-pay', $token);
return $this->api('confirm-assure-portfoli-pay', $data);
}
@ -466,4 +462,126 @@ class Baofu
$data['authContent'] = $params['authContent'];
return $this->api('auth-bind', $data);
}
public function queryOrder($params){
$data = [];
$data['loginNo'] = $params['loginNo'];
$data['tradeId'] = $params['tradeId'];
return $this->api('query-order', $data);
}
public function transferWithdraw($params) {
$items = [];
foreach ($params['transContent'] as $transItem) {
$item = [];
$item['transNo'] = $transItem['transNo'];
$item['transMoney'] = $transItem['transMoney'];
$item['transType'] = $transItem['transType'];
$item['transAccNo'] = $transItem['transAccNo'];
$item['transAccName'] = $transItem['transAccName'];
$item['transSummary'] = $transItem['transSummary'] ?? '转账';
if ($transItem['transType'] == 0) {
// 付款类型为银行时 传银行信息
$item['cardBankName'] = $transItem['cardBankName'];
$item['cardProName'] = $transItem['cardProName'];
$item['cardCityName'] = $transItem['cardCityName'];
$item['cardAccDept'] = $transItem['cardAccDept'];
$item['cardCnap'] = $transItem['cardCnap'];
$item['transIdCard'] = $transItem['transIdCard'];
$item['transMobile'] = $transItem['transMobile'];
}
ksort($item);
$items[] = $item;
}
$body = ['transContent' => $items];
return $this->unionPayPost($body, 'T-1001-003-01');
}
public function transferWithdrawQuery($params) {
$items = [];
foreach ($params['transContent'] as $transItem) {
$item = [];
$item['transNo'] = $transItem['transNo'];
$item['transBatchId'] = $transItem['transBatchId'];
ksort($item);
$items[] = $item;
}
$body = ['transContent' => $items];
return $this->unionPayPost($body, 'T-1001-003-02');
}
private function unionPayPost($body, $serviceTp) {
$header = [];
$header['memberId'] = $this->getMerchantNo();
$header['terminalId'] = $this->getTerminalNo();
$header['serviceTp'] = $serviceTp;
$header['verifyType'] = 1;
$content = [
'header' => $header,
'body' => $body,
];
ksort($content);
echo json_encode($content);
echo PHP_EOL;
$contentSign = Rsa::encryptedByPrivateKey(json_encode($content), $this->getPfxFilePath(), $this->getPrivateKeyPassword());
$header['content'] = $contentSign;
echo json_encode($header);
echo PHP_EOL;
$url = 'https://public.baofu.com/union-gw/api/' . $header['serviceTp'] . '/transReq.do';
$response = HttpClient::post($url, $header);
echo $response;
echo PHP_EOL;
$result = Rsa::decryptByPublicKey($response, $this->getCerFilePath());
echo $result;
echo PHP_EOL;
$result = json_decode($result, true);
if ($result['header']['sysRespCode'] == 'S_0000' && $result['body']['transHeader']['returnCode'] == '0000') {
return $result['body']['transContent'];
} else {
$msg = $result['header']['sysRespCode'] == 'S_0000' ? $result['body']['transHeader']['returnMsg'] : $result['header']['sysRespDesc'];
throw new BusinessException($msg);
}
}
public function decryptUnionPayData($content) {
return Rsa::decryptByPublicKey($content, $this->getCerFilePath());
}
public function signWithdrawEntrust($loginNo, $token)
{
$data = [];
$data['loginNo'] = $loginNo;
return $this->h5('sign-withdraw-entrust', $data, $token);
}
public function unbindWithdrawEntrust($loginNo, $token)
{
$data = [];
$data['loginNo'] = $loginNo;
return $this->h5('unbind-withdraw-entrust', $data, $token);
}
public function entrustWithdraw($params, $token)
{
$data = [];
$data['amount'] = $params['amount'];
$data['loginNo'] = $params['loginNo'];
$data['agreementNo'] = Rsa::encryptByCERFile($params['agreementNo'], $this->getCerFilePath());
$data['outOrderNo'] = $params['outOrderNo'];
$data['notifyUrl'] = NotifyList::getNotifyUrl('withdraw', $token);
return $this->withReturnUrl($this->api('entrust-withdraw', $data), $token);
}
public function findSignEntrustResult($loginNo, $agreementType = 'W_ENTRUST')
{
$data = [];
$data['loginNo'] = $loginNo;
$data['agreementType'] = $agreementType;
return $this->api('find-sign-entrust-result', $data);
}
}

@ -58,6 +58,18 @@ class H5List
'signParams' => 'orgNo|merchantNo|terminalNo|callType|loginNo|requestDate|null',
'callType' => 'BM_PWDMODIFY'
],
'sign-withdraw-entrust' => [
'description' => '委托提现授权',
'url' => '/api/wallet/v3.0.0/login',
'signParams' => 'orgNo|merchantNo|terminalNo|callType|loginNo|requestDate|dataContent',
'callType' => 'SIGN_WITHDRAW_ENTRUST',
],
'unbind-withdraw-entrust' => [
'description' => '委托提现解权',
'url' => '/api/wallet/v3.0.0/login',
'signParams' => 'orgNo|merchantNo|terminalNo|callType|loginNo|requestDate|dataContent',
'callType' => 'UNBIND_WITHDRAW_ENTRUST',
],
];
public static function get($h5Name)

@ -22,6 +22,7 @@ class HttpClient {
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Content-Length: ' . strlen($postDataString)));
} else {
$postDataString = http_build_query($postData);//格式化参数
echo $postDataString;
}
curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); //对认证证书来源的检查

@ -48,6 +48,10 @@ class NotifyList
'description' => '自助交易确认分账',
'signParams' => 'orgNo|merchantNo|terminalNo|tradeId|subOutOrderNo|orderStatus|loginId|finishTime|confirmType',
],
'confirm-assure-portfolio-pay' => [
'description' => '确认分账',
'signParams' => 'orgNo|merchantNo|terminalNo|tradeId|subOutOrderNo|orderStatus|loginId|finishTime|confirmType',
],
'refund' => [
'description' => '退款',
'signParams' => 'orgNo|merchantNo|terminalNo|refundOrderId|refundTradeId|refundMoney|refundStatus|refundSuccTime|refundType|errorMsg',

@ -13,6 +13,9 @@ class StringHelper
const ORDER_NO_TYPE_UNBIND_CARD = 'unbind_card';
const ORDER_NO_TYPE_QUERY_CUSTOMER_INFO = 'query_customer_info';
const ORDER_NO_TYPE_REQUEST_ID = 'request_id';
const ORDER_NO_TYPE_WITHDRAW_APPLY_BATCH_NUM = 'withdraw_apply_batch_num';
const ORDER_NO_TYPE_WITHDRAW_APPLY_NO = 'withdraw_apply_no';
const ORDER_NO_TYPE_WITHDRAW_NO = 'withdraw_no';
public static function getRandomString($length, $withSpecialChar = false)
{

@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace App\Model;
class Withdraw extends Model
{
protected $table = 'withdraws';
public function app()
{
return $this->belongsTo(App::class, 'app_id', 'app_id');
}
}

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace App\Model;
class WithdrawApply extends Model
{
public const STATUS_PREPARE = 'PREPARE';
public const STATUS_APPLY_SUCCESS = 'APPLY_SUCCESS';
public const STATUS_APPLY_FAILED = 'APPLY_FAILED';
public const STATUS_REFUND = 'REFUND';
public const STATUS_PROCESS = 'PROCESS';
public const STATUS_SUCCESS = 'SUCCESS';
public const STATUS_FAILED = 'FAILED';
protected $table = 'withdraw_applies';
public function app()
{
return $this->belongsTo(App::class, 'app_id', 'app_id');
}
public static $shortStatusAndStatusMap = [
'0' => self::STATUS_PROCESS,
'1' => self::STATUS_SUCCESS,
'-1' => self::STATUS_FAILED,
'2' => self::STATUS_REFUND,
];
public static function getStatusByShortStatus($shortStatus)
{
return self::$shortStatusAndStatusMap[$shortStatus] ?: null;
}
}

@ -15,6 +15,8 @@ use App\Model\OrderSplitInfo;
use App\Model\Refund;
use App\Model\RefundSplitInfo;
use App\Model\User;
use App\Model\Withdraw;
use App\Model\WithdrawApply;
class PaymentService extends AbstractService
{
@ -36,11 +38,19 @@ class PaymentService extends AbstractService
throw new BusinessException('订单号重复');
}
[$order, $orderSplitInfos] = $this->createOrder($app, $data, $user, 'paymentSplit');
$data['payType'] = $data['payType'] ?? 'CARD';
$payMethod = $data['payMethod'] ?? 'paymentSplit';
[$order, $orderSplitInfos] = $this->createOrder($app, $data, $user, $payMethod);
$splitInfoList = $this->buildSplitInfoList($orderSplitInfos);
return $this->paymentSplit($order, $user, $splitInfoList, $token);
if ($payMethod == 'paymentSplit') {
return $this->paymentSplit($order, $user, $splitInfoList, $token);
} elseif($payMethod == 'unionPay') {
return $this->unionPay($order, $user, $splitInfoList, $token);
} else {
throw new BusinessException('payMethod不支持');
}
}
public function transferPay(array $data, App $app, string $token)
@ -83,7 +93,7 @@ class PaymentService extends AbstractService
'loginNo' => $user->member_id,
'outOrderNo' => $order->order_no,
'amount' => $order->amount,
'paidType' => 'CARD',
'paidType' => $order->pay_type,
'agreementNo' => $order->agreement_no,
'pwdPayExpTime' => $order->expires_in,
'splitInfoList' => $splitInfoList,
@ -92,7 +102,7 @@ class PaymentService extends AbstractService
$order->applied_at = date('Y-m-d H:i:s');
$order->pay_url = $url;
$order->save();
return $url;
return ['url' => $url];
} catch (ApiException $e) {
$order->status = 'APPLY_FAILED';
$order->applied_at = date('Y-m-d H:i:s');
@ -133,6 +143,43 @@ class PaymentService extends AbstractService
}
}
private function unionPay(Order $order, User $user, array $splitInfoList, string $token)
{
// ASSURE_SHARE
// ASSURE_PAYMENT
// ASSURE_PORTFOLIO_PAY
// PAYMENT_SPLIT
try {
$baofu = new Baofu();
$result = $baofu->payment([
'loginNo' => $user->member_id,
'outOrderNo' => $order->order_no,
'goodsName' => $order->goods_name,
'amount' => $order->amount,
'paidType' => $order->pay_type,
'agreementNo' => $order->agreement_no,
'expireDate' => date('YmdHis', time() + $order->expires_in),
'validDate' => date('Ymd', $order->valid_date ? strtotime($order->valid_date) : time()),
'splitInfoList' => $splitInfoList,
'chanalId' => $order->channel_id,
'appId' => $order->channel_app_id,
'callType' => 'PAYMENT_SPLIT',
], $token);
$order->status = 'APPLY_SUCCESS';
$order->applied_at = date('Y-m-d H:i:s');
$order->acs_no = $result['body'] ?? '';
$order->save();
return $result;
} catch (ApiException $e) {
$order->status = 'APPLY_FAILED';
$order->applied_at = date('Y-m-d H:i:s');
$order->error_code = $e->getErrorCode();
$order->error_message = $e->getMessage();
$order->save();
throw $e;
}
}
public function createOrder(App $app, array $params, User $user, string $payMethod) {
if ($params['amount'] < 10) {
throw new BusinessException('金额不能小于10');
@ -150,14 +197,18 @@ class PaymentService extends AbstractService
$order->return_url = $params['returnUrl'] ?? '';
$order->agreement_no = $params['agreementNo'] ?? '';
$order->status = 'PREPARE';
$order->pay_mode = 'BAOFU';
$order->channel_id = $params['channelId'] ?? '';
$order->channel_app_id = $params['appId'] ?? '';
$order->pay_channel = 'BAOFU';
$order->pay_method = $payMethod;
$order->pay_type = 'CARD';
$order->pay_type = $params['payType'] ?? '';
$order->valid_date = $params['validDate'] ?? null;
$order->expires_in = $expiresIn;
$order->expired_at = date('Y-m-d H:i:s', time() + $expiresIn);
$order->market_info = $params['marketInfo'] ?? [];
$order->org_split_info_list = $params['splitInfoList'];
$order->remark = $params['remark'] ?? '';
$order->save();
$platformAccount = User::getPlatformAccount();
@ -212,17 +263,22 @@ class PaymentService extends AbstractService
return [$order, $orderSplitInfos];
}
public function updateOrder($params) {
$order = Order::where('order_no', $params['order_no'])->where('status', 'APPLY_SUCCESS')->first();
public function updateOrder($params, array $statusList = null) {
$order = Order::where('order_no', $params['order_no'])->first();
if (empty($order)) {
return null;
}
if ($statusList && !in_array($order->status, $statusList)) {
return null;
}
$order->third_order_no = $params['third_order_no'];
$order->status = $params['status'];
$order->finished_at = date('Y-m-d H:i:s', strtotime($params['finished_at']));
$order->error_message = $params['error_message'];
$order->transaction_id = $params['transaction_id'];
$order->out_transaction_id = $params['out_transaction_id'];
$order->error_message = $params['error_message'] ?? '';
$order->transaction_id = $params['transaction_id'] ?? '';
$order->out_transaction_id = $params['out_transaction_id'] ?? '';
$order->save();
return $order;
}
@ -385,12 +441,12 @@ class PaymentService extends AbstractService
if (empty($user)) {
throw new BusinessException('用户不存在');
}
$order = Order::where('app_id', $app->app_id)->where('out_order_no', $data['outOrderNo'])->first();
$order = Order::where('app_id', $app->app_id)->where('out_order_no', $data['oldOutOrderNo'])->first();
if (empty($order)) {
throw new BusinessException('订单不存在');
}
if ($order->status != Order::STATUS_APPLY_SUCCESS) {
if ($order->status != Order::STATUS_SUCCESS) {
throw new BusinessException('订单状态异常');
}
@ -410,7 +466,6 @@ class PaymentService extends AbstractService
'assureConfirmSplitInfoList' => $confirmSplitInfoList,
'outOrderNo' => StringHelper::generateOrderNo(StringHelper::ORDER_NO_TYPE_CONFIRM_PAY),
'amount' => $data['amount'],
'notifyUrl' => $data['notifyUrl'],
], $token);
$order->status = 'CONFIRM_SUCCESS';
$order->save();
@ -423,4 +478,248 @@ class PaymentService extends AbstractService
throw $e;
}
}
public function queryOrder(array $data, App $app)
{
$type = $data['type'] ?? 'PAYMENT';
$orderNo = null;
$memberId = null;
if ($type == 'WITHDRAW') {
$withdraw = Withdraw::where('app_id', $app->app_id)->where('out_withdraw_no', $data['outOrderNo'])->first();
if (empty($withdraw)) {
throw new BusinessException('提现记录不存在');
}
$memberId = $withdraw->member_id;
$orderNo = $withdraw->withdraw_no;
} elseif ($type == 'PAYMENT') {
$order = Order::where('app_id', $app->app_id)->where('out_order_no', $data['outOrderNo'])->first();
if (empty($order)) {
throw new BusinessException('订单不存在');
}
$memberId = $order->member_id;
$orderNo = $order->order_no;
} else {
throw new BusinessException('查询类型错误');
}
$baofu = new Baofu();
$result = $baofu->queryOrder([
'loginNo' => $memberId,
'tradeId' => $orderNo,
]);
$info = [
'member_id' => $memberId,
'order_no' => $orderNo,
'third_order_no' => $result['requestNo'] ?? '',
'status' => $result['status'],
'amount' => $result['amount'],
'fee' => $result['feeAmt'] ?? 0,
'fee_acc' => $result['feeAcc'] ?? 0,
'finished_at' => $result['finishDate'],
'error_message' => $result['errorMsg'] ?? '',
'transaction_id' => $result['transactionId'] ?? '',
'out_transaction_id' => $result['outTransactionId'] ?? '',
];
if ($result['tradeType'] == 'WITHDRAW') {
return $this->updateWithdraw($info);
} elseif (in_array($result['tradeType'], ['ASSURE_RECHARGE', 'PAYMENT_SPLIT_API', 'ASSURE_PORTFOLIO_PAY'])) {
return $this->updateOrder($info);
} else {
return true;
}
}
public function withdrawApply(array $data, App $app) {
$user = User::where('app_id', $app->app_id)->where('user_id', $data['userId'])->first();
if (empty($user)) {
throw new BusinessException('用户不存在');
}
$apply = new WithdrawApply();
$apply->app_id = $app->app_id;
$apply->user_id = $user->user_id;
$apply->member_id = $user->member_id;
$apply->account_name = $data['accountName'];
$apply->batch_num = StringHelper::generateOrderNo(StringHelper::ORDER_NO_TYPE_WITHDRAW_APPLY_BATCH_NUM);
$apply->apply_no = StringHelper::generateOrderNo(StringHelper::ORDER_NO_TYPE_WITHDRAW_APPLY_NO);
$apply->out_apply_no = $data['outApplyNo'];
$apply->notify_url = $data['notifyUrl'];
$apply->amount = $data['amount'];
$apply->status = 'PREPARE';
$apply->summary = $data['summary'] ?? '转账';
$apply->applied_at = date('Y-m-d H:i:s');
$apply->save();
$baofu = new Baofu();
$data = [
'transContent' => [
[
'transNo' => $apply->apply_no,
'transMoney' => round($apply->amount / 100, 2),
'transType' => 2,
'transAccNo' => $user->contract_no,
'transAccName' => $apply->account_name,
'transSummary' => $apply->summary,
]
]
];
try {
$result = $baofu->transferWithdraw($data);
$apply->third_apply_no = $result[0]['transOrderId'];
$apply->third_batch_num = $result[0]['transBatchId'];
$apply->status = 'APPLY_SUCCESS';
$apply->save();
return ['batchNum' => $apply->batch_num, 'applyNo' => $apply->apply_no];
} catch (ApiException $e) {
$apply->status = 'APPLY_FAILED';
$apply->error_code = $e->getCode();
$apply->error_message = $e->getMessage();
$apply->save();
throw $e;
}
}
public function withdrawApplyQuery(array $data, App $app) {
$user = User::where('app_id', $app->app_id)->where('user_id', $data['userId'])->first();
if (empty($user)) {
throw new BusinessException('用户不存在');
}
$apply = WithdrawApply::where('app_id', $app->app_id)->where('out_apply_no', $data['outApplyNo'])->first();
$baofu = new Baofu();
$data = [
'transContent' => [
[
'transNo' => $apply->apply_no,
'transBatchId' => $apply->third_batch_num,
]
]
];
try {
$result = $baofu->transferWithdrawQuery($data);
$item = $result[0];
$apply->fee = intval($item['transFee'] * 100);
$apply->third_apply_no = $item['transOrderId'];
$apply->third_batch_num = $item['transBatchId'];
$apply->status = WithdrawApply::getStatusByShortStatus($item['state']);
$apply->save();
return ['fee' => $apply->fee, 'status' => $apply->status, 'amount' => $apply->amount];
} catch (ApiException $e) {
throw $e;
}
}
public function withdraw(array $data, App $app, string $token) {
$withdrawType = $data['withdrawType'] ?? 'normal';
$user = User::where('app_id', $app->app_id)->where('user_id', $data['userId'])->first();
if (empty($user)) {
throw new BusinessException('用户不存在');
}
$withdraw = new Withdraw();
$withdraw->app_id = $app->app_id;
$withdraw->user_id = $user->user_id;
$withdraw->member_id = $user->member_id;
$withdraw->agreement_no = $data['agreementNo'];
$withdraw->withdraw_no = StringHelper::generateOrderNo(StringHelper::ORDER_NO_TYPE_WITHDRAW_NO);
$withdraw->out_withdraw_no = $data['outWithdrawNo'];
$withdraw->withdraw_type = $withdrawType;
$withdraw->amount = $data['amount'];
$withdraw->status = 'PREPARE';
$withdraw->applied_at = date('Y-m-d H:i:s');
$withdraw->notify_url = $data['notifyUrl'];
$withdraw->save();
if ($withdrawType == 'entrust') {
return $this->doEntrustWithdraw($data, $withdraw, $token);
} else {
return $this->doWithdraw($data, $withdraw, $token);
}
}
private function doWithdraw(array $data, Withdraw $withdraw, string $token) {
try {
$baofu = new Baofu();
$result = $baofu->withdraw([
'amount' => intval($data['amount']),
'loginNo' => $withdraw->member_id,
'agreementNo' => $data['agreementNo'],
'outOrderNo' => $withdraw->withdraw_no,
], $token);
$withdraw->status = 'APPLY_SUCCESS';
$withdraw->withdraw_url = $result;
$withdraw->save();
return $result;
} catch (ApiException $e) {
$withdraw->status = 'APPLY_FAILED';
$withdraw->error_code = $e->getCode();
$withdraw->error_message = $e->getMessage();
$withdraw->save();
throw $e;
}
}
private function doEntrustWithdraw(array $data, Withdraw $withdraw, string $token) {
try {
$baofu = new Baofu();
$result = $baofu->entrustWithdraw([
'amount' => intval($data['amount']),
'loginNo' => $withdraw->member_id,
'agreementNo' => $data['agreementNo'],
'outOrderNo' => $withdraw->withdraw_no,
], $token);
$withdraw->status = 'APPLY_SUCCESS';
$withdraw->withdraw_url = $result;
$withdraw->save();
return $result;
} catch (ApiException $e) {
$withdraw->status = 'APPLY_FAILED';
$withdraw->error_code = $e->getCode();
$withdraw->error_message = $e->getMessage();
$withdraw->save();
throw $e;
}
}
public function updateWithdraw($params, array $statusList = null) {
$withdraw = Withdraw::where('withdraw_no', $params['order_no'])->first();
if (empty($withdraw)) {
return null;
}
if ($statusList && !in_array($withdraw->status, $statusList)) {
return null;
}
$withdraw->third_withdraw_no = $params['third_order_no'];
$withdraw->status = $params['status'];
$withdraw->fee = $params['fee'] ?? 0;
$withdraw->fee_acc = $params['fee_acc'] ?? 0;
$withdraw->finished_at = $params['finished_at'] ?? null;
$withdraw->save();
return $withdraw;
}
public function updateWithdrawApply($params, array $statusList = null) {
$apply = WithdrawApply::where('apply_no', $params['transNo'])->first();
if (empty($apply)) {
return null;
}
if ($statusList && !in_array($apply->status, $statusList)) {
return null;
}
$apply->fee = intval($params['transFee'] * 100);
$apply->third_apply_no = $params['transOrderId'];
$apply->third_batch_num = $params['transBatchId'];
$apply->status = WithdrawApply::getStatusByShortStatus($params['state']);
$apply->save();
return $apply;
}
}

@ -234,4 +234,40 @@ class UserService extends AbstractService
$baofu = new Baofu();
return $baofu->getBalance($memberId);
}
public function signWithdrawEntrust(array $data, App $app, string $token)
{
$user = User::where('app_id', $app->app_id)->where('user_id', $data['userId'])->first();
if (empty($user)) {
throw new BusinessException('用户不存在');
}
$baofu = new Baofu();
$url = $baofu->signWithdrawEntrust($user->member_id, $token);
return $url;
}
public function unbindWithdrawEntrust(array $data, App $app, string $token)
{
$user = User::where('app_id', $app->app_id)->where('user_id', $data['userId'])->first();
if (empty($user)) {
throw new BusinessException('用户不存在');
}
$baofu = new Baofu();
$url = $baofu->unbindWithdrawEntrust($user->member_id, $token);
return $url;
}
public function querySignEntrust(array $data, App $app)
{
$user = User::where('app_id', $app->app_id)->where('user_id', $data['userId'])->first();
if (empty($user)) {
throw new BusinessException('用户不存在');
}
$baofu = new Baofu();
$result = $baofu->findSignEntrustResult($user->member_id);
return $result;
}
}

@ -21,8 +21,8 @@ return [
'orgNo' => '1274207',
'terminalNo' => '82254',
'privateKeyPassword' => 'Ntp2Mx3MtqPZ',
'simIDWx' => '',
'simIDAli' => '',
'simIDWx' => '591432528',
'simIDAli' => '2088720811286939',
'channelId' => '',
'channelName' => '',
'pfxFilePath' => BASE_PATH . '/certs/prod/baofu-xy.pfx',

@ -20,7 +20,7 @@ return [
'name' => 'http',
'type' => Server::SERVER_HTTP,
'host' => '0.0.0.0',
'port' => env('HTTP_PORT', 9501),
'port' => (int)env('HTTP_PORT', 9501),
'sock_type' => SWOOLE_SOCK_TCP,
'callbacks' => [
Event::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],

@ -19,12 +19,21 @@ Router::addGroup('/payment',function () {
Router::post('/pwd-forget', [PaymentController::class, 'pwdForget']);
Router::post('/pwd-modify', [PaymentController::class, 'pwdModify']);
Router::post('/payment', [PaymentController::class, 'payment']);
Router::post('/get-balance', [PaymentController::class, 'getBalance']);
Router::post('/confirm-pay', [PaymentController::class, 'confirmPay']);
Router::post('/query-order', [PaymentController::class, 'queryOrder']);
Router::post('/transfer-pay', [PaymentController::class, 'transferPay']);
Router::post('/query-bind-cards', [PaymentController::class, 'queryBindCards']);
Router::post('/query-user', [PaymentController::class, 'queryUser']);
Router::post('/refund-apply', [PaymentController::class, 'refundApply']);
Router::post('/refund-confirm', [PaymentController::class, 'refundConfirm']);
Router::post('/refund-cancel', [PaymentController::class, 'refundCancel']);
Router::post('/withdraw-apply', [PaymentController::class, 'withdrawApply']);
Router::post('/withdraw-apply-query', [PaymentController::class, 'withdrawApplyQuery']);
Router::post('/withdraw', [PaymentController::class, 'withdraw']);
Router::post('/unbind-withdraw-entrust', [PaymentController::class, 'unbindWithdrawEntrust']);
Router::post('/sign-withdraw-entrust', [PaymentController::class, 'signWithdrawEntrust']);
Router::post('/query-sign-entrust', [PaymentController::class, 'querySignEntrust']);
}, ['middleware' => [\App\Middleware\RequestLogMiddleware::class, \App\Middleware\AppAuthMiddleWare::class]]);
Router::addGroup('/notify',function () {
@ -32,7 +41,10 @@ Router::addGroup('/notify',function () {
Router::addRoute(['GET', 'POST'], '/bind-card/{token}', [NotifyController::class, 'bindCard']);
Router::addRoute(['GET', 'POST'], '/payment/{token}', [NotifyController::class, 'payment']);
Router::addRoute(['GET', 'POST'], '/refund/{token}', [NotifyController::class, 'refund']);
Router::addRoute(['GET', 'POST'], '/withdraw/{token}', [NotifyController::class, 'withdraw']);
Router::addRoute(['GET', 'POST'], '/transfer-withdraw', [NotifyController::class, 'transferWithdraw']);
Router::addRoute(['POST'], '/test-notify', [NotifyController::class, 'testNotify']);
Router::addRoute(['GET', 'POST'], '/confirm-assure-portfolio-pay/{token}', [NotifyController::class, 'confirmAssurePortfolioPay']);
});
Router::addRoute(['GET', 'POST'], '/return/{token}', [ReturnController::class, 'go']);

@ -224,4 +224,67 @@ add column `market_info` varchar(255) NOT NULL DEFAULT '' after valid_date,
add column `acs_no` varchar(32) NOT NULL DEFAULT '' after market_info;
alter table orders
add column `goods_name` varchar(125) NOT NULL DEFAULT '' after amount;
add column `goods_name` varchar(125) NOT NULL DEFAULT '' after amount;
alter table orders
add column `pay_mode` varchar(20) NOT NULL DEFAULT '' after market_info,
add column `remark` varchar(255) NOT NULL DEFAULT '' after return_url;
alter table orders
add column `channel_id` varchar(32) NOT NULL DEFAULT '' after market_info,
add column `channel_app_id` varchar(32) NOT NULL DEFAULT '' after market_info;
CREATE TABLE `withdraws` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`app_id` varchar(16) NOT NULL COMMENT '应用ID',
`member_id` varchar(32) NOT NULL,
`user_id` varchar(32) NOT NULL,
`withdraw_no` varchar(32) NOT NULL,
`out_withdraw_no` varchar(32) NOT NULL,
`amount` int(11) NOT NULL DEFAULT 0,
`agreement_no` varchar(32) NOT NULL DEFAULT '',
`fee` int(11) NOT NULL DEFAULT 0,
`fee_acc` tinyint(1) NOT NULL DEFAULT 0,
`withdraw_url` varchar(255) NOT NULL DEFAULT '',
`applied_at` datetime DEFAULT NULL,
`notify_url` varchar(255) NOT NULL DEFAULT '',
`status` varchar(16) NOT NULL DEFAULT '',
`error_code` varchar(64) NOT NULL DEFAULT '',
`error_message` varchar(120) NOT NULL DEFAULT '',
`finished_at` datetime DEFAULT NULL,
`third_withdraw_no` varchar(32) NOT NULL DEFAULT '',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_appid` (`app_id`) USING BTREE,
KEY `idx_memberid` (`member_id`) USING BTREE,
KEY `idx_createdat` (`created_at`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC;
CREATE TABLE `withdraw_applies` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`app_id` varchar(16) NOT NULL COMMENT '应用ID',
`member_id` varchar(32) NOT NULL,
`user_id` varchar(32) NOT NULL,
`apply_no` varchar(32) NOT NULL,
`batch_num` varchar(32) NOT NULL,
`out_apply_no` varchar(32) NOT NULL,
`amount` int(11) NOT NULL DEFAULT 0,
`fee` int(11) NOT NULL DEFAULT 0,
`account_name` varchar(32) NOT NULL DEFAULT '',
`summary` varchar(255) NOT NULL DEFAULT '',
`applied_at` datetime DEFAULT NULL,
`notify_url` varchar(255) NOT NULL DEFAULT '',
`status` varchar(16) NOT NULL DEFAULT '',
`error_code` varchar(64) NOT NULL DEFAULT '',
`error_message` varchar(120) NOT NULL DEFAULT '',
`third_apply_no` varchar(32) NOT NULL DEFAULT '',
`third_batch_num` varchar(32) NOT NULL DEFAULT '',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_appid` (`app_id`) USING BTREE,
KEY `idx_memberid` (`member_id`) USING BTREE,
KEY `idx_createdat` (`created_at`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC;

@ -1,84 +1,154 @@
<?php
/** ======================================================= */
/**
* 提现申请(资金从平台户到用户电子账户)
* url: payment/withdraw-apply
*
*/
$data = [
'userId' => 'ELF1990',
'accountName' => '廖金灵',
'outApplyNo' => time() . rand(1000, 9999),
'amount' => '10',
'summary' => '测试',
'notifyUrl' => 'http://124.223.222.61:9501/notify/test-notify'
];
/*
同步返回结果data
{
"batchNum": "2023083102511200001",
"applyNo": "2023083102511200001"
}
*/
/*
异步返回结果:
{
"amount": 1,
"status": "SUCCESS",
"userId": "abc",
"outApplyNo": "2023083102511200001"
}
*/
/** ======================================================= */
/**
* 提现到绑定银行卡(资金从用户电子账户到用户绑定银行卡)
* url: payment/withdraw
*
*/
$data = [
'userId' => 'ELF1990',
'agreementNo' => '312023082200002060225',
'outWithdrawNo' => time() . rand(1000, 9999),
'amount' => '1',
'notifyUrl' => 'http://124.223.222.61:9501/notify/test-notify',
'returnUrl' => 'https://www.baidu.com',
];
/*
同步返回结果data
{
"url": "http://xxxxxxx", // 输入支付密码url
}
异步返回结果data
{
"amount": 1,
"status": "SUCCESS",
"userId": "abc",
"outWithdrawNo": "2023083102511200001" // 传入的提现号
}
*/
/** ======================================================= */
/**
* 查询提现申请结果
* url: payment/withdraw-apply-query
*
*/
$data = [
'userId' => 'ELF1990',
'outApplyNo' => '16934203547527',
];
/*
同步返回结果data
{
"amount": 1,
"status": "SUCCESS",
"fee": 0, // 手续费
}
*/
/** ======================================================= */
/**
* 查询提现结果(原接口改造)
* url: payment/query-order
*/
$data = [
'type' => 'WITHDRAW',
'outOrderNo' => '16934198607215',
];
// 同步返回结果与原来相同
$params = [
'app_id' => '202306140000001',
'timestamp' => time(),
'nonce_str' => getRandomString(32),
'data' => json_encode([
'outOrderNo' => time().rand(1000, 9999),
'outMemberId' => 'T001',
'amount' => 100,
'notifyUrl' => 'https://www.baidu.com',
]),
/** ======================================================= */
// 一般有以下状态
const STATUS_APPLY_SUCCESS = 'APPLY_SUCCESS'; // 申请失败
const STATUS_APPLY_FAILED = 'APPLY_FAILED'; // 申请成功
const STATUS_REFUND = 'REFUND'; // 已退款
const STATUS_PROCESS = 'PROCESS'; // 处理中
const STATUS_SUCCESS = 'SUCCESS'; // 成功
const STATUS_FAILED = 'FAILED'; // 失败
/**
* 委托提现授权
* url: payment/sign-withdraw-entrust
*
*/
$data = [
'userId' => 'ELF1990',
];
$params['sign'] = sign($params, 'nM2bUJT89njQGzoeDyK8cLmEYJloUsJX');
$response = post('http://66.42.38.42:9501/payment/pay', json_encode($params));
var_dump(json_decode($response, true));die();
// select * from `orders` where `app_id` = '202306140000001' and `out_order_no` = '16869297292619' limit 1
$params = [
'app_id' => '202306140000001',
'timestamp' => time(),
'nonce_str' => getRandomString(32),
'data' => json_encode([
'outOrderNo' => '16869297292619',
]),
/*
同步返回结果data
{
"url": "xxxxxxxx",
}
*/
/**
* 解除委托提现授权
* url: payment/unbind-withdraw-entrust
*
*/
$data = [
'userId' => 'ELF1990',
];
$params['sign'] = sign($params, 'nM2bUJT89njQGzoeDyK8cLmEYJloUsJX');
$response = post('http://146.70.113.165:9501/payment/query', json_encode($params));
var_dump(json_decode($response, true));
function post($url, $jsonStr) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonStr);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json; charset=utf-8',
'Content-Length: ' . strlen($jsonStr)
)
);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $response;
/*
同步返回结果data
{
"url": "xxxxxxxx",
}
*/
function sign($params, $secretKey) {
$signString = $params['app_id'] . '&'
. $params['timestamp'] . '&'
. $params['nonce_str'] . '&'
. $params['data'] . '&'
. $secretKey;
return md5($signString);
/**
* 委托提现授权结果查询
* url: payment/query-sign-entrust
*
*/
$data = [
'userId' => 'ELF1990',
];
/*
同步返回结果data
{
"result": true,
}
*/
function getRandomString($length, $withSpecialChar = false)
{
$chars = array(
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2',
'3', '4', '5', '6', '7', '8', '9'
);
if($withSpecialChar){
$chars = array_merge($chars, array(
'!', '@', '#', '$', '?', '|', '{', '/', ':', ';',
'%', '^', '&', '*', '(', ')', '-', '_', '[', ']',
'}', '<', '>', '~', '+', '=', ',', '.'
));
}
$charsLen = count($chars) - 1;
shuffle($chars);
$password = '';
for($i=0; $i<$length; $i++){
$password .= $chars[mt_rand(0, $charsLen)];
}
return $password;
}
// 委托提现接口同提现接口: payment/withdraw
// 新增参数 withdrawType (normal: 普通提现(默认) entrust: 委托授权提现)
Loading…
Cancel
Save