Compare commits

...

178 Commits

Author SHA1 Message Date
ljl d17c99740d yh 10 months ago
ljl 4ab728c6bf yh 10 months ago
ljl 0a050ace77 yh 10 months ago
ljl da9c440406 吸怪 10 months ago
ljl 3e2d7560b9 修改 10 months ago
elf deb887c5ff y 10 months ago
elf cb0525103e 修改 10 months ago
elf a026018135 修改 10 months ago
elf 003c72792b yh 11 months ago
elf 6bd739b7a0 yh 11 months ago
ljl 1e24db4af5 yh 11 months ago
ljl 3aabf5df8f yh 11 months ago
ljl 561c268d32 yh 11 months ago
ljl 70364cf545 yh 11 months ago
ljl 79c143ed65 yh 11 months ago
ljl 3b84849e83 yh 11 months ago
ljl 9813df702d yh 11 months ago
ljl 3aef834c3c yh 11 months ago
ljl fc2f8c9192 yh 11 months ago
ljl 723ff9977c yh 11 months ago
ljl bc52aa15bd yh 11 months ago
ljl 32318040ea yh 11 months ago
ljl 2ae0f34f72 yh 11 months ago
elf a5a91fd1e6 yh 11 months ago
elf 7d90bc8b10 yh 11 months ago
elf 1dbb1ae5a1 yh 11 months ago
elf 138d18ce6b yh 11 months ago
elf 80d3be778c yh 11 months ago
elf 7d7c9571ce yh 11 months ago
elf 48e30dba57 yh 11 months ago
elf 24b9fad1ed yh 11 months ago
elf 798c214dc1 yh 11 months ago
elf 27c1fe60ea yh 11 months ago
elf 283b5a9b26 yh 11 months ago
elf 47da0be3e9 yh 11 months ago
elf 39e58147b4 yg 11 months ago
elf d9504bff46 yg 11 months ago
elf 5f5f8fc1e4 yg 11 months ago
elf 9dc6937589 yg 11 months ago
elf d2b3fd4e49 yg 11 months ago
elf 7c154e0528 yg 11 months ago
ljl d9f2d88f78 yh 11 months ago
ljl 4ac8335a9c yh 11 months ago
ljl 78d2be5ecd yh 11 months ago
ljl f3538e77c3 yh 11 months ago
ljl 5082d68140 yh 11 months ago
ljl c07cba2c4e yh 11 months ago
ljl 1fd89184dc yh 11 months ago
ljl 8ce603078b yh 11 months ago
ljl 84e5de04be yh 11 months ago
ljl d62b3d0b31 yh 11 months ago
ljl af57b939f1 yh 11 months ago
ljl 1667d23bf6 yh 11 months ago
ljl e7161e1257 yh 11 months ago
ljl 9a648279e5 yh 11 months ago
ljl 8e5e2da9b2 yh 11 months ago
ljl 68f702b016 yh 11 months ago
ljl c14f3a9183 yh 11 months ago
elf c0a35feeb5 yh 11 months ago
elf e363a30efc yh 11 months ago
elf 383b30c391 yh 11 months ago
elf 2a30fe3056 yh 11 months ago
elf d5e3fbda53 yh 11 months ago
elf fe9eb8ea21 yh 11 months ago
elf 6579590481 yh 11 months ago
elf eaa50d7c4d yh 11 months ago
elf db1a1f4836 yh 11 months ago
elf bfef5f89d1 yh 11 months ago
elf 2033a091df yh 11 months ago
elf 37d1c52aab yh 11 months ago
elf 295733c4c9 yh 11 months ago
elf d2fd3abee6 yh 11 months ago
elf 75eb8401be yh 11 months ago
elf 919b5dee02 yh 11 months ago
elf 75293323dc yh 11 months ago
elf 759824d42e yh 11 months ago
elf 0055e51483 yh 11 months ago
elf 0c9d207ed4 yh 11 months ago
elf 04f7820458 yh 11 months ago
elf 548696c475 yh 11 months ago
elf 1a9ccda1fe yh 11 months ago
elf 63fa8078f4 yh 11 months ago
elf b509a24849 yh 11 months ago
elf 8534cd0539 yh 11 months ago
elf 2b067e6535 yh 11 months ago
elf a3da3e8758 yh 11 months ago
elf 469c26b830 yh 11 months ago
elf f79f13050d yh 11 months ago
elf f3b8aee2bc yh 11 months ago
elf ea759b2286 yh 11 months ago
elf 35acd7d85a yh 11 months ago
elf 6f6dbdc34c yh 11 months ago
elf 05a22e0654 yh 11 months ago
elf d00d4e0d0e yh 11 months ago
elf 6dcdb45938 修改 11 months ago
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,34 @@ class MineCommand extends HyperfCommand
public function handle(): void
{
$this->withdraw();
$this->getBalance();
return;
$result = $baofu->applyBindCard($user->member_id, [
'cardNo' => '80094800000009440000053437',
'cardName' => '福建省万瑞天成企业管理服务有限公司',
'bankName' => '厦门国际银行',
'branchName' => '厦门国际银行股份有限公司',
'provinceName' => '福建省',
'cityName' => '福建省厦门市',
], 'xxxxxxxxxxxxxxxxxx');
var_dump($result);
return;
$this->querySignEntrust('ACT_5');
$this->getBalance();
return;
$this->rsyncUser('289a092602845b1a40793db5409333f5', '202308070000001', 'ACT_5');
$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 +128,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);
@ -137,7 +244,7 @@ class MineCommand extends HyperfCommand
* @var UserService $userService
*/
$userService = $this->container->make(UserService::class);
$userService->rsyncUser($memberId, $appId, $userId);
$userService->rsyncUser($memberId, $appId, $userId, 'MERCHANT');
}
protected function rsyncBankCards() {
@ -145,7 +252,7 @@ class MineCommand extends HyperfCommand
* @var UserService $userService
*/
$userService = $this->container->make(UserService::class);
$userService->rsyncBankCards('4673f922e30cfd2efeeb992ff6a32ece');
$userService->rsyncBankCards('289a092602845b1a40793db5409333f5');
}
protected function bindCard()
@ -154,7 +261,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 +271,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);
}
@ -238,6 +345,14 @@ class MineCommand extends HyperfCommand
echo 'RLX: ' . $result . PHP_EOL;
$result = $userService->getBalance('f27f7786068387029a126de736bb84b2');
echo 'WHQ: ' . $result . PHP_EOL;
$result = $userService->getBalance('f9c0bea79725d71cc7969571c345de54');
echo 'CWX: ' . $result . PHP_EOL;
$result = $userService->getBalance('289a092602845b1a40793db5409333f5');
echo 'WRTC: ' . $result . PHP_EOL;
$user = User::where('user_id', 'ACT_9')->first();
$result = $userService->getBalance($user->member_id);
echo 'NEW: ' . $result . PHP_EOL;
}
public function refund()
@ -307,7 +422,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 +444,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());
var_dump($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', 'f9c0bea79725d71cc7969571c345de54')->first();
$baofu = new Baofu();
$result = $baofu->withdraw([
'amount' => intval(84558),
'loginNo' => 'f9c0bea79725d71cc7969571c345de54',
'agreementNo' => $bankCard->agreement_no,
'outOrderNo' => time() . rand(1000, 9999),
], 'elf');
var_dump($result);
}
}

@ -0,0 +1,75 @@
<?php
declare(strict_types=1);
namespace App\Command;
use App\Model\Order;
use App\Service\PaymentService;
use App\Service\RequestService;
use Hyperf\Command\Annotation\Command;
use Hyperf\Command\Command as HyperfCommand;
use Hyperf\Contract\ContainerInterface;
/**
* @Command
*/
class PaymentCommand extends HyperfCommand
{
/**
* @var ContainerInterface
*/
protected $container;
protected $admin;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
parent::__construct('payment');
}
public function configure(): void
{
parent::configure();
$this->setDescription('支付');
}
public function handle(): void
{
$this->confirmPay();
}
public function confirmPay()
{
/**
* @var PaymentService $paymentService
*/
$paymentService = $this->container->make(PaymentService::class);
$endTime = date('Y-m-d H:i:s', time() - 6*60);
$beginTime = date('Y-m-d H:i:s', time() - 20*60);
$orders = Order::where('updated_at', '>=', $beginTime)->where('updated_at', '<=', $endTime)->where('status', 'SUCCESS')->get();
foreach ($orders as $order) {
if ($order->user_id != 'ELF1990' && strpos($order->user_id, 'ACT_') !== 0) {
continue;
}
$userId = $order->user_id;
$requestLog = $this->createRequestLog(['userId' => $userId, 'oldOutOrderNo' => $order->out_order_no, 'amount' => $order->amount]);
$result = $paymentService->confirmPay($requestLog->getData(), $requestLog->app, $requestLog->request_token);
}
}
private function createRequestLog($data) {
/**
* @var RequestService $requestService
*/
$requestService = $this->container->make(RequestService::class);
$params = [
'app_id' => '202308070000001',
'data' => json_encode($data),
];
return $requestService->createRequestLog('', $params);
}
}

@ -0,0 +1,101 @@
<?php
declare(strict_types=1);
namespace App\Command;
use App\Helper\StringHelper;
use App\Model\BankCard;
use App\Model\Order;
use App\Model\User;
use App\Service\PaymentService;
use App\Service\RequestService;
use App\Service\UserService;
use Hyperf\Command\Annotation\Command;
use Hyperf\Command\Command as HyperfCommand;
use Hyperf\Contract\ContainerInterface;
/**
* @Command
*/
class WithdrawCommand extends HyperfCommand
{
/**
* @var ContainerInterface
*/
protected $container;
protected $admin;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
parent::__construct('withdraw');
}
public function configure(): void
{
parent::configure();
$this->setDescription('提现');
}
public function handle(): void
{
$this->confirmPay();
}
public function confirmPay()
{
/**
* @var PaymentService $paymentService
*/
$paymentService = $this->container->make(PaymentService::class);
/**
* @var UserService $userService
*/
$userService = $this->container->make(UserService::class);
$user = User::where('user_id', 'ACT_9')->first();
$balance = $userService->getBalance($user->member_id);
echo 'before balance: ' . $balance . PHP_EOL;
if ($balance == 0) {
return;
}
$bankCard = BankCard::where('user_id', $user->user_id)->first();
$requestLog = $this->createRequestLog([
'userId' => $user->user_id,
'withdrawType' => 'entrust',
'agreementNo' => $bankCard->agreement_no,
'outWithdrawNo' => StringHelper::generateOrderNo(StringHelper::ORDER_NO_TYPE_ACCOUNT_WITHDRAW),
'amount' => $balance,
'notifyUrl' => 'http://124.223.222.61:9701/notify/test-notify'
]);
$url = $paymentService->withdraw($requestLog->getData(), $requestLog->app, $requestLog->request_token);
echo 'result: ' . $url . PHP_EOL;
$balance = $userService->getBalance($user->member_id);
echo 'after balance: ' . $balance . PHP_EOL;
}
private function createRequestLog($data) {
/**
* @var RequestService $requestService
*/
$requestService = $this->container->make(RequestService::class);
$params = [
'app_id' => '202308070000001',
'data' => json_encode($data),
];
return $requestService->createRequestLog('', $params);
}
}

@ -0,0 +1,319 @@
<?php
declare(strict_types=1);
namespace App\Controller\Payment;
use App\Exception\BusinessException;
use App\Helper\Redis;
use App\Helper\RedisKey;
use App\Helper\StringHelper;
use App\Model\Account;
use App\Model\BankCard;
use App\Model\Order;
use App\Model\User;
use Hyperf\HttpServer\Contract\RequestInterface;
use App\Service\PaymentService;
use App\Service\RequestService;
use App\Service\UserService;
use Hyperf\DbConnection\Db;
class AccountController extends AbstractController
{
private RequestService $requestService;
private UserService $userService;
private PaymentService $paymentService;
public function __construct(RequestService $requestService, PaymentService $paymentService, UserService $userService)
{
$this->requestService = $requestService;
$this->userService = $userService;
$this->paymentService = $paymentService;
}
private function createRequestLog($data) {
$params = [
'app_id' => '202308070000001',
'data' => json_encode($data),
];
return $this->requestService->createRequestLog('', $params);
}
private function checkUser(RequestInterface $request) {
$token = $request->input('token');
if (empty($token)) {
throw new BusinessException('未登录');
}
$result = Redis::get(RedisKey::getUserTokenKey($token));
if (empty($result)) {
throw new BusinessException('未登录');
}
$userInfo = json_decode($result, true);
if (empty($userInfo)) {
throw new BusinessException('未登录');
}
return $userInfo;
}
public function register(RequestInterface $request)
{
throw new BusinessException('暂停使用');
$username = $request->input('username');
$password = $request->input('password');
if (strlen($username) < 6 || strlen($username) > 20) {
throw new BusinessException('账号必须为620位');
}
if (strlen($password) < 6 || strlen($password) > 20) {
throw new BusinessException('密码必须为620位');
}
$account = Account::where('username', $username)->first();
if (!empty($account)) {
throw new BusinessException('账号已存在');
}
$account = new Account();
$account->salt = StringHelper::getRandomString(6);
$account->username = $username;
$account->password = md5($password . $account->salt);
$account->save();
return $this->success();
}
public function login(RequestInterface $request)
{
$username = $request->input('username');
$password = $request->input('password');
if ($username != 'wcheng') {
throw new BusinessException('暂停使用');
}
$account = Account::where('username', $username)->first();
if (empty($account)) {
throw new BusinessException('账号或密码错误');
}
if (md5($password . $account->salt) != $account->password) {
throw new BusinessException('账号或密码错误');
}
$userInfo = json_encode(['userId' => $account->id]);
$token = StringHelper::getRandomString(16);
Redis::set(RedisKey::getUserTokenKey($token), $userInfo);
Redis::expire(RedisKey::getUserTokenKey($token), 3600);
return $this->success(['token' => $token]);
}
public function updatePassword(RequestInterface $request)
{
$userInfo = $this->checkUser($request);
$oldPassword = $request->input('oldPassword');
$password = $request->input('password');
$account = Account::where('id', $userInfo['userId'])->first();
if (md5($oldPassword . $account->salt) != $account->password) {
throw new BusinessException('旧密码错误');
}
$account->password = md5($password . $account->salt);
$account->save();
return $this->success();
}
public function openAccount(RequestInterface $request)
{
$userInfo = $this->checkUser($request);
$userId = $this->resetUserId($userInfo['userId']);
$requestLog = $this->createRequestLog(['userId' => $userId, 'returnUrl' => 'http://124.223.222.61:9701/account.html']);
$url = $this->userService->register($requestLog->getData(), $requestLog->app, $requestLog->request_token);
return $this->success(['url' => $url]);
}
public function bindCard(RequestInterface $request)
{
$userInfo = $this->checkUser($request);
$userId = $this->resetUserId($userInfo['userId']);
$requestLog = $this->createRequestLog(['userId' => $userId, 'returnUrl' => 'http://124.223.222.61:9701/account.html']);
$url = $this->userService->bindCard($requestLog->getData(), $requestLog->app, $requestLog->request_token);
return $this->success(['url' => $url]);
}
public function unbindCard(RequestInterface $request)
{
$userInfo = $this->checkUser($request);
$userId = $this->resetUserId($userInfo['userId']);
$bankCard = BankCard::where('id', $request->input('id', 0))->first();
if (!$bankCard || $bankCard->user_id != $userId) {
throw new BusinessException('银行卡不存在');
}
$requestLog = $this->createRequestLog(['userId' => $userId, 'agreementNo' => $bankCard->agreement_no]);
$result = $this->userService->unbindCard($requestLog->getData(), $requestLog->app);
return $this->success(['result' => $result]);
}
public function setPayPassword(RequestInterface $request)
{
$userInfo = $this->checkUser($request);
$userId = $this->resetUserId($userInfo['userId']);
$requestLog = $this->createRequestLog(['userId' => $userId, 'returnUrl' => 'http://124.223.222.61:9701/account.html']);
$url = $this->userService->pwdForget($requestLog->getData(), $requestLog->app, $requestLog->request_token);
return $this->success(['url' => $url]);
}
public function resetPayPassword(RequestInterface $request)
{
$userInfo = $this->checkUser($request);
$userId = $this->resetUserId($userInfo['userId']);
$requestLog = $this->createRequestLog(['userId' => $userId, 'returnUrl' => 'http://124.223.222.61:9701/account.html']);
$url = $this->userService->pwdModify($requestLog->getData(), $requestLog->app, $requestLog->request_token);
return $this->success(['url' => $url]);
}
public function transferPay(RequestInterface $request)
{
$userInfo = $this->checkUser($request);
$userId = $this->resetUserId($userInfo['userId']);
$bankCard = BankCard::where('user_id', $userId)->first();
$outOrderNo = StringHelper::generateOrderNo(StringHelper::ORDER_NO_TYPE_ACCOUNT_PAY);
$requestLog = $this->createRequestLog([
'userId' => $userId,
'goodsName' => '充值',
'agreementNo' => $bankCard->agreement_no,
'notifyUrl' => '',
'returnUrl' => 'http://124.223.222.61:9701/account.html',
'amount' => intval($request->input('amount') * 100),
'outOrderNo' => $outOrderNo,
'validDate' => date('Y-m-d', time() + 12*3600),
'marketInfo' => [
'amount' => 0,
'remark' => 'test',
],
'splitInfoList' => [
],
'isAccountPay' => true
]);
$acsNo = $this->paymentService->transferPay($requestLog->getData(), $requestLog->app, $requestLog->request_token);
return $this->success(['acsNo' => $acsNo, 'outOrderNo' => $outOrderNo]);
}
public function getUserInfo(RequestInterface $request)
{
$userInfo = $this->checkUser($request);
$account = Account::where('id', $userInfo['userId'])->first();
$userId = $this->resetUserId($userInfo['userId']);
$user = User::where('user_id', $userId)->first(['member_id', 'user_type']);
if ($user) {
$this->userService->rsyncUser($user->member_id, '202308070000001', $userId, $user->user_type);
$user = User::where('user_id', $userId)->first(['member_id', 'realname_flag', 'bind_card_flag', 'set_pwd_flag', 'mobile', 'real_name', 'certificate_no', 'user_type', 'apply_no', 'is_platform_account']);
$this->userService->rsyncBankCards($user->member_id);
}
$bankCard = BankCard::where('user_id', $userId)->first(['id', 'bank_name', 'card_user_name']);
return $this->success(['username' => $account->username, 'userInfo' => $user, 'bankCard' => $bankCard]);
}
private function resetUserId($accountId) {
if ($accountId == 2) {
return 'ELF1990';
}
return 'ACT_' . $accountId;
}
public function companyRegister(RequestInterface $request)
{
$userInfo = $this->checkUser($request);
$userId = $this->resetUserId($userInfo['userId']);
$requestLog = $this->createRequestLog(['userId' => $userId, 'email' => $request->input('email'), 'returnUrl' => 'http://124.223.222.61:9701/account.html']);
$url = $this->userService->companyRegister($requestLog->getData(), $requestLog->app, $requestLog->request_token);
return $this->success(['url' => $url]);
}
public function signWithdrawEntrust(RequestInterface $request)
{
$userInfo = $this->checkUser($request);
$userId = $this->resetUserId($userInfo['userId']);
$requestLog = $this->createRequestLog(['userId' => $userId, 'returnUrl' => 'http://124.223.222.61:9701/account.html']);
$url = $this->userService->signWithdrawEntrust($requestLog->getData(), $requestLog->app, $requestLog->request_token);
return $this->success(['url' => $url]);
}
public function getOrders(RequestInterface $request)
{
$userInfo = $this->checkUser($request);
$userId = $this->resetUserId($userInfo['userId']);
$query = Order::query()->with('user')->where('is_account_pay', 1);
if ($userId != 'ACT_9') {
$query->where('user_id', $userId);
}
if (!empty($request->input('outOrderNo'))) {
$query->where('out_order_no', $request->input('outOrderNo'));
}
if (!empty($request->input('mobile'))) {
$query->where('bank_mobile', $request->input('mobile'));
}
if (!empty($request->input('bankCardNo'))) {
$query->where('last_card_no', $request->input('bankCardNo'));
}
if (!empty($request->input('cardUserName'))) {
$query->where('card_user_name', 'like', '%' . $request->input('cardUserName'));
}
$status = $request->input('status');
if (!empty($status)) {
$statusList = [];
if ($status == 'FAILED') {
$statusList = ['APPLY_FAILED', 'FAILED'];
} elseif ($status == 'FINISH') {
$statusList = ['CONFIRM_SUCCESS', 'FINISH'];
} elseif ($status == 'SUCCESS') {
$statusList = ['SUCCESS'];
} elseif ($status == 'CONFIRM_FAILED') {
$statusList = ['CONFIRM_FAILED'];
} elseif ($status == 'PROCESS') {
$statusList = ['APPLY_SUCCESS', 'PROCESS'];
}
$query->whereIn('status', $statusList);
}
$timeRange = $request->input('timeRange');
if (!empty($timeRange)) {
$timeRange[0] .= ' 00:00:00';
$timeRange[1] .= ' 23:59:59';
$query->whereBetween('created_at', $timeRange);
}
$countQuery = clone $query;
$sumQuery = clone $query;
$total = $countQuery->count();
$amount = $sumQuery->sum('amount');
$orders = $query->get();
$records = [];
foreach ($orders as $order) {
$statusText = '';
$systemStatus = '';
if (in_array($order->status, ['APPLY_FAILED', 'FAILED'])) {
$statusText = '转账失败';
$systemStatus = 'FAILED';
} elseif (in_array($order->status, ['CONFIRM_SUCCESS', 'FINISH'])) {
$statusText = '转账成功,入账成功';
$systemStatus = 'FINISH';
} elseif (in_array($order->status, ['SUCCESS'])) {
$statusText = '转账成功,待入账';
$systemStatus = 'SUCCESS';
} elseif (in_array($order->status, ['CONFIRM_FAILED'])) {
$statusText = '转账成功,入账失败';
$systemStatus = 'CONFIRM_FAILED';
} elseif (in_array($order->status, ['APPLY_SUCCESS', 'PROCESS'])) {
$statusText = '待转账';
$systemStatus = 'PROCESS';
}
$records[] = [
'out_order_no' => $order->out_order_no,
'created_at' => $order->created_at->format('Y-m-d H:i:s'),
'status' => $order->status,
'amount' => number_format($order->amount / 100, 2, '.', ''),
'card_user_name' => $order->card_user_name,
'last_card_no' => $order->last_card_no,
'bank_mobile' => $order->bank_mobile,
'certificate_no' => $order->user->certificate_no,
'status' => $order->status,
'system_status' => $systemStatus,
'status_text' => $statusText,
];
}
return $this->success(['records' => $records, 'total' => $total, 'amount' => number_format($amount / 100, 2, '.', '')]);
}
}

@ -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';
}
}
}

@ -57,8 +57,8 @@ class PaymentController extends AbstractController
public function unbindCard(RequestInterface $request)
{
[$app, $data, $token] = $this->parseReqest($request, UnbindCardRequest::class);
$data = $this->userService->unbindCard($data, $app);
return $this->success($data);
$this->userService->unbindCard($data, $app);
return $this->success();
}
public function pwdForget(RequestInterface $request)
@ -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,25 +98,32 @@ 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);
return $this->success($data);
$this->paymentService->refundApply($data, $app);
return $this->success();
}
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);
return $this->success($data);
$this->paymentService->refundApply($data, $app);
return $this->success();
}
public function queryBindCards(RequestInterface $request)
@ -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);
}
@ -364,7 +360,7 @@ class Baofu
{
$data = [];
$data['loginNo'] = $loginNo;
$data['cardNo'] = BFRSA::encryptByCERFile($info['cardNo'], config('baofu.cerFilePath'));
$data['cardNo'] = Rsa::encryptByCERFile($info['cardNo'], $this->getCerFilePath());
$data['cardName'] = $info['cardName'];
$data['bankName'] = $info['bankName'];
$data['branchName'] = $info['branchName'];
@ -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',

@ -29,4 +29,8 @@ class RedisKey
public static function getRequestTokenKey($token) {
return 'request_token:' . $token;
}
public static function getUserTokenKey($token) {
return 'user_token:' . $token;
}
}

@ -13,6 +13,11 @@ 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';
const ORDER_NO_TYPE_ACCOUNT_WITHDRAW = 'account_withdraw';
const ORDER_NO_TYPE_ACCOUNT_PAY = 'account_pay';
public static function getRandomString($length, $withSpecialChar = false)
{

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace App\Model;
class Account extends Model
{
protected $table = 'accounts';
}

@ -29,4 +29,9 @@ class Order extends Model
{
return $this->hasMany(OrderSplitInfo::class, 'order_no', 'order_no');
}
public function user()
{
return $this->belongsTo(User::class, 'member_id', 'member_id');
}
}

@ -8,7 +8,10 @@ class User extends Model
{
protected $table = 'users';
public static function getPlatformAccount() {
public static function getPlatformAccount($isAccountPay) {
if ($isAccountPay) {
return self::where('user_id', 'ACT_4')->first();
}
return self::where('is_platform_account', 1)->first();
}
}

@ -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;
}
}

@ -10,11 +10,14 @@ use App\Exception\BusinessException;
use App\Helper\Baofu\Baofu;
use App\Helper\StringHelper;
use App\Model\App;
use App\Model\BankCard;
use App\Model\Order;
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 +39,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 +94,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 +103,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,10 +144,51 @@ 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');
}
$bankCard = BankCard::where('app_id', $app->app_id)->where('user_id', $user->user_id)->where('agreement_no', $params['agreementNo'])->first();
if (!$bankCard) {
throw new BusinessException('银行卡不存在');
}
$expiresIn = $params['expiresIn'] ?? 10 * 60;
$order = new Order();
$order->app_id = $app->app_id;
@ -150,21 +202,40 @@ 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->last_card_no = $bankCard->last_card_no;
$order->card_user_name = $bankCard->card_user_name;
$order->bank_mobile = $bankCard->bank_mobile;
$order->bank_name = $bankCard->bank_name;
$order->bank_code = $bankCard->bank_code;
$order->card_type = $bankCard->card_type;
$order->cnaps_code = $bankCard->cnaps_code;
$order->is_account_pay = isset($params['isAccountPay']) && $params['isAccountPay'] ? 1 :0;
$order->save();
$platformAccount = User::getPlatformAccount();
$fee = $platformAccount ? floor($order->amount * 0.007) : 0;
$platformAccount = User::getPlatformAccount($params['isAccountPay']);
$feeRate = 0.007;
// if ($params['isAccountPay']) {
// $feeRate = 0.00256;
// }
$fee = $platformAccount ? floor($order->amount * $feeRate) : 0;
if ($fee <= 0) {
$fee = 1;
}
if ($params['isAccountPay']) {
$fee = 200;
}
$orderSplitInfos = [];
$splitUserIds = array_column($params['splitInfoList'], 'splitUserId');
$users = User::where('app_id', $app->app_id)->whereIn('user_id', $splitUserIds)->get()->keyBy('user_id');
@ -208,21 +279,45 @@ class PaymentService extends AbstractService
'seller_flag' => 0,
];
}
if ($params['isAccountPay']) {
$feeSubOrderNo = StringHelper::generateOrderNo(StringHelper::ORDER_NO_TYPE_PAY_SPLIT);
$mainAccount = User::where('user_id', 'ACT_9')->first();
$orderSplitInfos[] = [
'app_id' => $app->app_id,
'user_id' => $user->user_id,
'member_id' => $user->member_id,
'split_member_id' => $mainAccount->member_id,
'split_user_id' => $mainAccount->user_id,
'split_user_type' => $mainAccount->user_type == 'MERCHANT' ? 'B_ACCOUNT' : $mainAccount->user_type,
'order_no' => $order->order_no,
'out_order_no' => $order->out_order_no,
'sub_order_no' => $feeSubOrderNo,
'sub_out_order_no' => $feeSubOrderNo,
'split_amount' => $order->amount - $fee,
'contract_no' => $mainAccount->contract_no,
'seller_flag' => 0,
];
}
OrderSplitInfo::insert($orderSplitInfos);
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 +480,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 +505,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 +517,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;
}
}

@ -41,9 +41,9 @@ class UserService extends AbstractService
return $url;
}
public function rsyncUser($memberId, $appId, $userId) {
public function rsyncUser($memberId, $appId, $userId, $customerType = 'PERSON') {
$baofu = new Baofu();
$userInfo = $baofu->queryCustomerInfo($memberId);
$userInfo = $baofu->queryCustomerInfo($memberId, $customerType);
return $this->saveUser($userInfo, $appId, $userId);
}
@ -71,7 +71,7 @@ class UserService extends AbstractService
$user->realname_flag = $userInfo['realNameFlag'] ?? 'Y';
$user->bind_card_flag = $userInfo['bindCardFlag'];
$user->set_pwd_flag = $userInfo['setPwdFlag'];
$user->status = $userInfo['operatorStatus'] ?: $userInfo['status'];
$user->status = $userInfo['status'];
$user->email = $userInfo['email'] ?? '';
$user->mobile = $userInfo['mobile'] ?? '';
$user->real_name = $userInfo['customerName'] ?? '';
@ -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'],

@ -2,6 +2,7 @@
declare(strict_types=1);
use App\Controller\Payment\AccountController;
use App\Controller\Payment\NotifyController;
use App\Controller\Payment\PaymentController;
use App\Controller\Payment\ReturnController;
@ -19,20 +20,48 @@ 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('/account',function () {
Router::post('/login', [AccountController::class, 'login']);
Router::post('/register', [AccountController::class, 'register']);
Router::post('/open-account', [AccountController::class, 'openAccount']);
Router::post('/bind-card', [AccountController::class, 'bindCard']);
Router::post('/unbind-card', [AccountController::class, 'unBindCard']);
Router::post('/set-pay-password', [AccountController::class, 'setPayPassword']);
Router::post('/reset-pay-password', [AccountController::class, 'resetPayPassword']);
Router::post('/transfer-pay', [AccountController::class, 'transferPay']);
Router::post('/user-info', [AccountController::class, 'getUserInfo']);
Router::get('/company-register', [AccountController::class, 'companyRegister']);
Router::post('/update-password', [AccountController::class, 'updatePassword']);
Router::get('/sign-withdraw-entrust', [AccountController::class, 'signWithdrawEntrust']);
Router::post('/get-orders', [AccountController::class, 'getOrders']);
}, []);
Router::addGroup('/notify',function () {
Router::addRoute(['GET', 'POST'], '/register/{token}', [NotifyController::class, 'register']);
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']);

@ -225,3 +225,66 @@ 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;
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;

@ -0,0 +1,464 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- import CSS -->
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/theme-chalk/index.min.css">
<title>我的账户</title>
</head>
<body>
<div id="app">
<el-container>
<el-main>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="账户信息" name="user">
<el-row>
<el-col :span="24">
<el-descriptions title="用户信息">
<el-descriptions-item label="用户名">{{username}} <el-button type="primary" @click="logout" size="mini" round>退出登录</el-button></el-descriptions-item>
<el-descriptions-item label="登录密码"><el-button type="primary" @click="updatePasswordVisible = true" size="mini" round>修改</el-button></el-descriptions-item>
</el-descriptions>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-descriptions title="开户信息">
<el-descriptions-item label="用户名" v-if="userInfo != null && userInfo.realname_flag==='Y'">{{userInfo.real_name}}</el-descriptions-item>
<el-descriptions-item label="用户名" v-else><el-button type="primary" @click="openAccount" size="mini" round>开户</el-button></el-descriptions-item>
<el-descriptions-item label="身份证号" v-if="userInfo != null && userInfo.realname_flag==='Y'">{{userInfo.certificate_no}}</el-descriptions-item>
<el-descriptions-item label="身份证号" v-else>--</el-descriptions-item>
<el-descriptions-item label="支付密码" v-if="userInfo != null && userInfo.set_pwd_flag==='Y'">********** <el-button type="primary" @click="resetPayPassword" size="mini" round>修改</el-button></el-descriptions-item>
<el-descriptions-item label="支付密码" v-else><el-button type="primary" @click="setPayPassword" size="mini" round>设置</el-button></el-descriptions-item>
</el-descriptions>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-descriptions title="绑卡信息">
<el-descriptions-item label="开户行" v-if="bankCard != null && userInfo.bind_card_flag!=='N'">{{bankCard.bank_name}} <el-button type="primary" @click="unbindCard" size="mini" round>解绑</el-button></el-descriptions-item>
<el-descriptions-item label="开户行" v-else><el-button type="primary" @click="bindCard" size="mini" round>绑卡</el-button></el-descriptions-item>
<el-descriptions-item label="开户姓名" v-if="bankCard != null && userInfo.bind_card_flag!=='N'">{{bankCard.card_user_name}}</el-descriptions-item>
<el-descriptions-item label="开户姓名" v-else>--</el-descriptions-item>
</el-descriptions>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="充值" name="recharge">
<div>
<el-form ref="payForm" :model="payForm" label-width="80px">
<el-form-item label="金额">
<el-input v-model="payForm.amount"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="transferPay">充值</el-button>
</el-form-item>
</el-form>
</div>
<div>
<h2>充值流程</h2>
<p>1. 输入金额,点击充值按钮</p>
<p>2. 按弹窗提示转账</p>
</div>
</el-tab-pane>
<el-tab-pane label="充值记录" name="orders">
<div>
<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.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-input v-model="search.cardUserName" 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="FINISH"></el-option>
<el-option label="转账成功,待入账" value="SUCCESS"></el-option>
<el-option label="转账成功,入账失败" value="CONFIRM_FAILED"></el-option>
<el-option label="转账失败" value="FAILED"></el-option>
<el-option label="待转账" value="PROCESS"></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
:data="records"
style="width: 100%">
<el-table-column
prop="out_order_no"
label="订单号"
width="180">
</el-table-column>
<el-table-column
prop="card_user_name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="certificate_no"
label="身份证号">
</el-table-column>
<el-table-column
prop="last_card_no"
label="银行卡号(后四位)">
</el-table-column>
<el-table-column
prop="bank_mobile"
label="手机号(后四位)">
</el-table-column>
<el-table-column
prop="amount"
label="充值金额">
</el-table-column>
<el-table-column
prop="created_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"
style="margin-top: 10px">
</el-pagination>
</el-col>
</el-row>
</div>
</el-tab-pane>
</el-tabs>
</el-main>
</el-container>
<el-dialog title="转账信息" :visible.sync="payInfoVisible" width="50%">
<div>
<h3>您可通过网银或手机银行app向专属打款账户进行转账其中</h3>
<p><el-tag type="success">订单号:{{outOrderNo}}</el-tag></p>
<p><el-tag type="success">户名:宝付网络科技(上海)有限公司</el-tag></p>
<p><el-tag type="success">银行:支付机构备付金集中存管账户</p>
<p><el-tag type="success">开户城市:上海</el-tag></p>
<p><el-tag type="success">开户网点:宝付网络-备付金账户</el-tag></p>
<p><el-tag type="success">行号991290000793</el-tag></p>
<p><el-tag type="success">专属打款账户:{{acsNo}}</el-tag></p>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="payInfoVisible = false">确 定</el-button>
</div>
</el-dialog>
<el-dialog title="修改登录密码" :visible.sync="updatePasswordVisible" width="40%">
<div>
<el-form ref="updatePasswordForm" :model="updatePasswordForm" label-width="80px">
<el-form-item label="原密码">
<el-input show-password v-model="updatePasswordForm.oldPassword"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input show-password v-model="updatePasswordForm.password"></el-input>
</el-form-item>
<el-form-item label="确认密码">
<el-input show-password v-model="updatePasswordForm.confirm_password"></el-input>
</el-form-item>
</el-form>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="updatePasswordVisible = false">取 消</el-button>
<el-button type="primary" @click="updatePassword">确 定</el-button>
</div>
</el-dialog>
</div>
</body>
<!-- import Vue before Element -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.9/vue.min.js"></script>
<!-- import JavaScript -->
<script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/index.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.min.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
activeName: 'user',
updatePasswordVisible: false,
username: '',
payForm: {
amount: 0
},
userInfo: {
realname_flag: '',
bind_card_flag: '',
mobile: '',
real_name: '',
certificate_no: '',
user_type: '',
apply_no: '',
is_platform_account: ''
},
updatePasswordForm: {
oldPassword: '',
password: '',
confirm_password: ''
},
bankCard: {
id: 0,
bank_name: '',
card_user_name: ''
},
acsNo: '',
outOrderNo: '',
payInfoVisible: false,
search: {
mobile: '',
cardNo: '',
bankCardNo: '',
orderNo: '',
outOrderNo: '',
cardUserName: '',
timeRange: null,
status: undefined
},
records: [],
total: 0,
amount: 0,
pageSize: 20
}
},
created() {
if (!window.sessionStorage.getItem('token')) {
window.location.href = '/login.html'
return;
} else {
this.getUserInfo();
}
},
methods: {
logout() {
window.sessionStorage.removeItem('token');
window.location.href = '/login.html';
},
getUserInfo() {
axios.post('/account/user-info', {token: window.sessionStorage.getItem('token')})
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
this.$message.error(response.data.message);
window.sessionStorage.removeItem('token');
window.location.href = '/login.html';
return;
}
this.username = result.data.username;
this.userInfo = result.data.userInfo;
this.bankCard = result.data.bankCard;
console.log('result', result);
console.log('username', this.username);
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
},
openAccount() {
axios.post('/account/open-account', {token: window.sessionStorage.getItem('token')})
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
return this.$message.error(response.data.message);
}
window.open(result.data.url)
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
},
updatePassword() {
if (this.updatePasswordForm.confirm_password != this.updatePasswordForm.password) {
this.$message.error('密码和确认密码不一致');
return;
}
axios.post('/account/update-password', {token: window.sessionStorage.getItem('token'), oldPassword: this.updatePasswordForm.oldPassword, password: this.updatePasswordForm.password})
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
return this.$message.error(response.data.message);
}
this.$message.success('修改成功');
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
},
resetPayPassword() {
axios.post('/account/reset-pay-password', {token: window.sessionStorage.getItem('token')})
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
return this.$message.error(response.data.message);
}
window.open(result.data.url)
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
},
setPayPassword() {
axios.post('/account/set-pay-password', {token: window.sessionStorage.getItem('token')})
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
return this.$message.error(response.data.message);
}
window.open(result.data.url)
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
},
bindCard() {
axios.post('/account/bind-card', {token: window.sessionStorage.getItem('token')})
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
return this.$message.error(response.data.message);
}
window.open(result.data.url)
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
},
unbindCard() {
axios.post('/account/unbind-card', {token: window.sessionStorage.getItem('token'), id: this.bankCard.id})
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
return this.$message.error(response.data.message);
}
if (result.data.result) {
this.$message.success('解绑成功');
window.location.href = window.location.href;
} else {
return this.$message.error('解绑失败');
}
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
},
transferPay() {
axios.post('/account/transfer-pay', {token: window.sessionStorage.getItem('token'), amount: this.payForm.amount})
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
return this.$message.error(response.data.message);
}
this.acsNo = result.data.acsNo;
this.outOrderNo = result.data.outOrderNo;
this.payInfoVisible = true;
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
},
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;
},
searchList(page) {
let data = {...this.search}
data.token = window.sessionStorage.getItem('token');
data.page = page;
data.pageSize = this.pageSize;
axios.post('/account/get-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;
this.amount = result.data.amount;
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
},
query() {
this.searchList(1)
},
handleCurrentChange(val) {
this.searchList(val)
},
handleClick(tab, event) {
console.log(tab)
if (tab.name === 'orders') {
this.searchList(1)
}
}
}
})
</script>
</html>

@ -0,0 +1,134 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- import CSS -->
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/theme-chalk/index.min.css">
<title>支付系统</title>
</head>
<body>
<div id="app">
<el-container>
<el-main>
<el-row>
<el-col :span="24">
<el-tabs v-model="activeName">
<el-tab-pane label="登录" name="login">
<el-form ref="loginForm" :model="loginForm" label-width="80px">
<el-form-item label="账号">
<el-input v-model="loginForm.username"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input show-password v-model="loginForm.password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="login">登录</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="注册" name="register">
<el-form ref="registerForm" :model="registerForm" label-width="80px">
<el-form-item label="账号">
<el-input v-model="registerForm.username"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input show-password v-model="registerForm.password"></el-input>
</el-form-item>
<el-form-item label="确认密码">
<el-input show-password v-model="registerForm.confirm_password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="register">注册</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
</el-col>
</el-row>
</el-main>
</el-container>
</div>
</body>
<!-- import Vue before Element -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.9/vue.min.js"></script>
<!-- import JavaScript -->
<script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/index.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.min.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
activeName: 'login',
loginForm: {
username: '',
password: ''
},
registerForm: {
username: '',
password: '',
confirm_password: ''
}
}
},
created() {
if (window.sessionStorage.getItem('token')) {
window.location.href = '/account.html'
return;
}
},
methods: {
register() {
if (this.registerForm.confirm_password != this.registerForm.password) {
this.$message.error('密码和确认密码不一致');
return;
}
axios.post('/account/register', this.registerForm)
.then( (response) => {
console.log(response);
let result = response.data
if (result.code != 1000) {
return this.$message.error(response.data.message);
}
this.activeName = 'login';
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
},
login() {
axios.post('/account/login', this.loginForm)
.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)
window.location.href = '/account.html';
})
.catch((error) => {
this.$message.error('请求错误');
console.log(error);
});
console.log('submit!');
},
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;
}
}
})
</script>
</html>

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<!-- import CSS -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/theme-chalk/index.min.css">
<title>充值记录</title>
</head>
<body>
@ -17,16 +17,13 @@
<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-input v-model="search.mobile" placeholder="手机尾号(后四位)" clearable></el-input>
</el-form-item>
<el-form-item label="">
<el-input v-model="search.cardNo" placeholder="身份证号" clearable></el-input>
<el-input v-model="search.bankCardNo" 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-input v-model="search.cardUserName" placeholder="名字(不加姓)" clearable></el-input>
</el-form-item>
<el-form-item label="">
<el-date-picker
@ -40,10 +37,11 @@
</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-option label="转账成功,入账成功" value="FINISH"></el-option>
<el-option label="转账成功,待入账" value="SUCCESS"></el-option>
<el-option label="转账成功,入账失败" value="CONFIRM_FAILED"></el-option>
<el-option label="转账失败" value="FAILED"></el-option>
<el-option label="待转账" value="PROCESS"></el-option>
</el-select>
</el-form-item>
<el-form-item>
@ -65,28 +63,28 @@
width="180">
</el-table-column>
<el-table-column
prop="real_name"
prop="card_user_name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="card_no"
prop="certificate_no"
label="身份证号">
</el-table-column>
<el-table-column
prop="bank_card_no"
label="银行卡号">
prop="last_card_no"
label="银行卡号(后四位)">
</el-table-column>
<el-table-column
prop="mobile"
label="手机号">
prop="bank_mobile"
label="手机号(后四位)">
</el-table-column>
<el-table-column
prop="amount"
label="充值金额">
</el-table-column>
<el-table-column
prop="payed_at"
prop="created_at"
label="充值时间">
</el-table-column>
<el-table-column
@ -106,59 +104,41 @@
</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>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.9/vue.min.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 src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/index.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.min.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
search: {
name: '',
mobile: '',
cardNo: '',
bankCardNo: '',
orderNo: '',
outOrderNo: '',
cardUserName: '',
timeRange: null,
status: undefined
},
records: [],
total: 0,
amount: 0,
pageSize: 20,
loginVisible: false,
loginer: {
username: '',
password: ''
}
pageSize: 20
}
},
created() {
if (!window.sessionStorage.getItem('token')) {
this.loginVisible = true;
return this.$message.error('请先登录');
window.location.href = '/login.html'
return;
} else {
this.searchList();
}
this.searchList();
},
methods: {
searchList(page) {
@ -166,7 +146,7 @@
data.token = window.sessionStorage.getItem('token');
data.page = page;
data.pageSize = this.pageSize;
axios.post('/recharge/orders', data)
axios.post('/account/get-orders', data)
.then( (response) => {
console.log(response);
let result = response.data
@ -191,24 +171,6 @@
},
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);
});
}
}
})

@ -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