efps-version
elf 1 year ago
parent c53bf7df08
commit 515771739f

@ -6,6 +6,8 @@ namespace App\Command;
use App\Helper\Efps\Api; use App\Helper\Efps\Api;
use App\Helper\Signer; use App\Helper\Signer;
use App\Helper\StringHelper;
use App\Request\RegisterRequest;
use App\Service\AppService; use App\Service\AppService;
use App\Service\MerchantService; use App\Service\MerchantService;
use App\Service\PaymentService; use App\Service\PaymentService;
@ -40,8 +42,40 @@ class JinlingCommand extends HyperfCommand
public function handle(): void public function handle(): void
{ {
/*Api::register([
'merId' => "100", // 562238003185933 $ret = Api::certifiedPayment([
'outTradeNo' => time() . rand(1000, 9999),
'userName' => 'abc',
'phoneNum' => '18760419185',
'bankCardNo' => '6214835911385365',
'certificatesNo' => '350824199001105476',
'payAmount' => 100,
]);
var_dump($ret);
return;
/*$ret = Api::unifiedPayment();
var_dump($ret);
return;*/
/*$params = [
'app_id' => '202304270000004',
'timestamp' => time(),
'nonce_str' => StringHelper::getRandomString(32),
'data' => json_encode([
'test' => 1,
]),
];
$sign = \App\Helper\Platform\Signer::sign($params, 'lSHKbuFngCXHN8Ue1s8QHAAzPvOL3u9O');
$params['sign'] = $sign;
var_dump($params);
$request = new RegisterRequest($params);
$params = $request->getData();
var_dump($params);
return;*/
/*$ret = Api::unifiedPayment();
var_dump($ret);
return;*/
$ret = Api::register([
'merId' => "T100", // 562238003185933
'backUrl' => 'http://www.baidu.com', 'backUrl' => 'http://www.baidu.com',
'certificateName' => '测试', 'certificateName' => '测试',
'lawyerCertType' => 0, 'lawyerCertType' => 0,
@ -52,16 +86,18 @@ class JinlingCommand extends HyperfCommand
'contactPhone' => '18888888888', 'contactPhone' => '18888888888',
'accountType' => 3, 'accountType' => 3,
'canDownType' => '01', 'canDownType' => '01',
]);*/ ]);
Api::bindCard([ var_dump($ret);
'memberId' => '562238003185933', return;
$ret = Api::bindCard([
'mchtOrderNo' => time() . rand(1000, 9999), 'mchtOrderNo' => time() . rand(1000, 9999),
'userName' => '测试', 'userName' => '廖金灵',
'phoneNum' => '18888888888', 'phoneNum' => '18760419185',
'bankCardNo' => '6214835911385365', 'bankCardNo' => '6214835911385365',
'bankCardType' => 'debit', 'bankCardType' => 'debit',
'certificatesNo' => '430481198104234557', 'certificatesNo' => '350824199001105476',
]); ]);
var_dump($ret);
return; return;
echo \App\Helper\Efps\Signer::sign('sss'); echo \App\Helper\Efps\Signer::sign('sss');
$sm3 = new \OneSm\Sm3(); $sm3 = new \OneSm\Sm3();

@ -4,26 +4,164 @@ declare(strict_types=1);
namespace App\Controller\Payment; namespace App\Controller\Payment;
use App\Service\PaymentService; use App\Helper\Efps\Signer;
use App\Helper\Log;
use App\Helper\Platform\Notification;
use App\Model\App;
use App\Model\Order;
use App\Model\RefundOrder;
use Hyperf\HttpServer\Contract\RequestInterface; use Hyperf\HttpServer\Contract\RequestInterface;
class NotifyController extends AbstractController class NotifyController extends AbstractController
{ {
private PaymentService $paymentService;
public function __construct(PaymentService $paymentService) public function __construct()
{ {
$this->paymentService = $paymentService;
} }
public function index(RequestInterface $request) public function payment(RequestInterface $request)
{ {
$params = $request->all(); $params = $request->all();
return $this->paymentService->notify($params); Log::info('paymentNotifyToOut params:', $params);
$sign = $request->getHeader('x-efps-sign');
$data = json_encode($params);
if (!Signer::verify($data, $sign)) {
Log::info('paymentNotifyToOut data: ' . $data . ' sign: ' . $sign);
return [
'returnCode' => '0001',
'returnMsg' => '签名验证失败'
];
}
$outOrderNo = $params['outTradeNo'] ?: '';
$order = Order::where('out_order_no', $outOrderNo)->first();
if (!$order) {
Log::info('paymentNotifyToOut: ' . '订单号不存在[' . $outOrderNo . ']');
return [
'returnCode' => '0000',
'returnMsg' => '处理成功'
];
}
$app = App::where('app_id', $order->app_id)->first();
if (!$app) {
Log::info('paymentNotifyToOut: ' . 'APP不存在[' . $outOrderNo . '][' . $order->app_id . ']');
return [
'returnCode' => '0000',
'returnMsg' => '处理成功'
];
}
if ($order->status != Order::STATUS_WAIT_PAY) {
return [
'returnCode' => '0000',
'returnMsg' => '处理成功'
];
}
if ($params['payState'] === '00') {
$order->status = Order::STATUS_PAYED;
$order->fee = $params['procedureFee'] ?: 0;
$order->pay_order_no = $params['transactionNo'] ?: '';
$order->channel_order_no = $params['channelOrder'] ?: '';
$order->payed_at = date('Y-m-d H:i:s');
$order->save();
} elseif ($params['payState'] === '01') {
$order->status = Order::STATUS_FAILED;
$order->error_code = '01';
$order->error_msg = '处理失败';
$order->payed_at = date('Y-m-d H:i:s');
$order->save();
}
$result = $this->notify($order->notify_url, $app, [
'outTradeNo' => $params['outTradeNo'] ?: '',
'transactionNo' => $params['transactionNo'] ?: '',
'payState' => $params['payState'],
'amount' => $params['amount'] ?: 0,
]);
Log::info('paymentNotifyToOut result: ' . '订单[' . $outOrderNo . '][' . $$result . ']');
return [
'returnCode' => '0000',
'returnMsg' => '处理成功'
];
} }
public function efps(RequestInterface $request) { public function refund(RequestInterface $request)
{
$params = $request->all(); $params = $request->all();
return $this->paymentService->efpsNotify($params); Log::info('refundNotifyToOut params:', $params);
$sign = $request->getHeader('x-efps-sign');
$data = json_encode($params);
if (!Signer::verify($data, $sign)) {
Log::info('refundNotifyToOut data: ' . $data . ' sign: ' . $sign);
return [
'returnCode' => '0001',
'returnMsg' => '签名验证失败'
];
}
$outRefundNo = $params['outRefundNo'] ?: '';
$order = RefundOrder::where('out_refund_order_no', $outRefundNo)->first();
if (!$order) {
Log::info('refundNotifyToOut: ' . '订单号不存在[' . $outRefundNo . ']');
return [
'returnCode' => '0000',
'returnMsg' => '处理成功'
];
}
$app = App::where('app_id', $order->app_id)->first();
if (!$app) {
Log::info('refundNotifyToOut: ' . 'APP不存在[' . $outRefundNo . '][' . $order->app_id . ']');
return [
'returnCode' => '0000',
'returnMsg' => '处理成功'
];
}
if ($order->status != RefundOrder::STATUS_APPLY_SUCCESS) {
return [
'returnCode' => '0000',
'returnMsg' => '处理成功'
];
}
if ($params['payState'] === '00') {
$order->status = RefundOrder::STATUS_REFUND_SUCCESS;
$order->fee = $params['procedureFee'] ?: 0;
$order->refunded_at = date('Y-m-d H:i:s');
$order->save();
} elseif ($params['payState'] === '01') {
$order->status = RefundOrder::STATUS_REFUND_FAILED;
$order->error_code = '01';
$order->error_msg = '处理失败';
$order->refunded_at = date('Y-m-d H:i:s');
$order->save();
}
$result = $this->notify($order->notify_url, $app, [
'outRefundNo' => $params['outRefundNo'] ?: '',
'transactionNo' => $params['transactionNo'] ?: '',
'payState' => $params['payState'],
'amount' => $params['amount'] ?: 0,
'refundAmount' => $params['refundAmount'] ?: 0,
]);
Log::info('paymentNotifyToOut result: ' . '订单[' . $outRefundNo . '][' . $$result . ']');
return [
'returnCode' => '0000',
'returnMsg' => '处理成功'
];
}
protected function notify($url, $app, $data) {
$params = [
'app_id' => $app->app_id,
'nonce_str' => StringHelper::getRandomString(32),
'timestamp' => time(),
];
$params['data'] = json_encode($data);
$params['sign'] = PlatformSigner::sign($params, $app->app_key);
Log::info('notifyToOut params:', $params, 'platform');
Log::info('notifyToOut url:' . $url, [], 'platform');
$result = Notification::post($url, $params);
Log::info('notifyToOut response:' . $result, [], 'platform');
return $result;
} }
} }

@ -6,11 +6,16 @@ namespace App\Controller\Payment;
use App\Exception\BusinessException; use App\Exception\BusinessException;
use App\Helper\Efps\Api; use App\Helper\Efps\Api;
use App\Model\Order;
use App\Model\RefundOrder;
use App\Model\User;
use App\Request\BindCardConfirmRequest; use App\Request\BindCardConfirmRequest;
use App\Request\BindCardRequest; use App\Request\BindCardRequest;
use App\Request\JsapiPayRequest; use App\Request\JsapiPayRequest;
use App\Request\ProtocolPayConfirmRequest; use App\Request\ProtocolPayConfirmRequest;
use App\Request\ProtocolPayPreRequest; use App\Request\ProtocolPayPreRequest;
use App\Request\RefundQueryRequest;
use App\Request\RefundRequest;
use App\Request\RegisterRequest; use App\Request\RegisterRequest;
use App\Request\UnBindCardRequest; use App\Request\UnBindCardRequest;
use Hyperf\HttpServer\Contract\RequestInterface; use Hyperf\HttpServer\Contract\RequestInterface;
@ -25,23 +30,26 @@ class PayController extends AbstractController
$this->paymentService = $paymentService; $this->paymentService = $paymentService;
} }
public function jsapi(RequestInterface $request)
{
$form = new JsapiPayRequest($request->all());
$order = $this->paymentService->jsapiPay($form->getApp(), $form->getData());
return $this->success([
'pay_url' => $order->pay_url,
'order_no' => $order->order_no,
]);
}
public function register(RequestInterface $request) public function register(RequestInterface $request)
{ {
$req = new RegisterRequest($request->all()); $req = new RegisterRequest($request->all());
$result = Api::register($req->getData()); $app = $req->getApp();
$data = $req->getData();
$result = Api::register($data);
if (!$result->isSuccess()) { if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage()); throw new BusinessException($result->getMessage());
} }
if ($result->get('auditState') == 1) {
$user = new User();
$user->app_id = $app->app_id;
$user->member_id = $result->get('memberId');
$user->merId = $data['merId'] ?: '';
$user->card_no = $data['lawyerCertNo'] ?: '';
$user->card_valid_to = $data['certificateTo'] ?: '';
$user->mobile = $data['contactPhone'] ?: '';
$user->save();
}
return $this->success($result->getData()); return $this->success($result->getData());
} }
@ -78,20 +86,95 @@ class PayController extends AbstractController
public function protocolPayPreRequest(RequestInterface $request) public function protocolPayPreRequest(RequestInterface $request)
{ {
$req = new ProtocolPayPreRequest($request->all()); $req = new ProtocolPayPreRequest($request->all());
$result = Api::protocolPayPre($req->getData()); $app = $req->getApp();
$data = $req->getData();
$result = Api::protocolPayPre($data);
$order = $this->paymentService->createOrder($app, $data);
if (!$result->isSuccess()) { if (!$result->isSuccess()) {
$order->status = Order::STATUS_APPLY_FAIL;
$order->save();
throw new BusinessException($result->getMessage()); throw new BusinessException($result->getMessage());
} }
$order->token = $result->get('token', '');
$order->protocol = $result->get('protocol', '');
$order->status = Order::STATUS_WAIT_PAY;
$order->save();
return $this->success($result->getData()); return $this->success($result->getData());
} }
public function protocolPayConfirm(RequestInterface $request) public function protocolPayConfirm(RequestInterface $request)
{ {
$req = new ProtocolPayConfirmRequest($request->all()); $req = new ProtocolPayConfirmRequest($request->all());
$app = $req->getApp();
$data = $req->getData();
$order = Order::where('app_id', $app->app_id)
->where('token', $data['token'])
->where('protocol', $data['protocol'])
->first();
if (!$order) {
throw new BusinessException('订单不存在');
}
$result = Api::protocolPayConfirm($req->getData()); $result = Api::protocolPayConfirm($req->getData());
if (!$result->isSuccess()) { if (!$result->isSuccess()) {
$order->status = Order::STATUS_FAILED;
$order->error_code = $result->getCode();
$order->error_msg = $result->getMessage();
$order->payed_at = date('Y-m-d H:i:s');
$order->save();
throw new BusinessException($result->getMessage());
}
// 00 01 03
$this->paymentService->handlePayResult($result, $order);
return $this->success($result->getData());
}
public function refund(RequestInterface $request) {
$req = new RefundRequest($request->all());
$app = $req->getApp();
$data = $req->getData();
$refundOrder = new RefundOrder();
$refundOrder->app_id = $app->app_id;
$refundOrder->out_order_no = $data['outTradeNo'] ?: '';
$refundOrder->out_refund_order_no = $data['outRefundNo'] ?: '';
$refundOrder->order_amount = $data['amount'] ?: '';
$refundOrder->refund_amount = $data['refundAmount'] ?: '';
$refundOrder->remark = $data['remark'] ?: '';
$refundOrder->notify_url = $data['notifyUrl'] ?: '';
$result = Api::refund($data);
if (!$result->isSuccess()) {
$refundOrder->status = RefundOrder::STATUS_APPLY_FAILED;
$refundOrder->error_code = $result->getCode();
$refundOrder->error_msg = $result->getMessage();
$refundOrder->save();
throw new BusinessException($result->getMessage()); throw new BusinessException($result->getMessage());
} }
$refundOrder->status = RefundOrder::STATUS_APPLY_SUCCESS;
$refundOrder->save();
return $this->success($result->getData()); return $this->success($result->getData());
} }
public function refundQuery(RequestInterface $request) {
$req = new RefundQueryRequest($request->all());
$data = $req->getData();
$result = Api::refundQuery($data);
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
return $this->success(
$result->getData([
'outRefundNo',
'transactionNo',
'amount',
'refundAmount',
'refundState'
])
);
}
} }

@ -7,6 +7,7 @@ namespace App\Exception\Handler;
use App\Constants\ResultCode; use App\Constants\ResultCode;
use App\Exception\BasicException; use App\Exception\BasicException;
use App\Helper\Result; use App\Helper\Result;
use Hyperf\Context\Context;
use Hyperf\Contract\StdoutLoggerInterface; use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\ExceptionHandler\ExceptionHandler; use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream; use Hyperf\HttpMessage\Stream\SwooleStream;
@ -54,6 +55,12 @@ class AppExceptionHandler extends ExceptionHandler
$this->logger->error($throwable->getTraceAsString()); $this->logger->error($throwable->getTraceAsString());
} }
$result = new Result($code, $message, $data); $result = new Result($code, $message, $data);
$requestLog = Context::get('requestLog');
if ($requestLog) {
$requestLog->response_data = json_encode($result->toArray(), JSON_UNESCAPED_UNICODE);
$requestLog->response_time = date('Y-m-d H:i:s');
$requestLog->save();
}
return $response return $response
->withAddedHeader('content-type', 'application/json; charset=utf-8') ->withAddedHeader('content-type', 'application/json; charset=utf-8')
->withStatus($httpCode) ->withStatus($httpCode)

@ -12,7 +12,7 @@ abstract class AbstractApi
{ {
protected static $client; protected static $client;
protected static $env = 'dev'; protected static $env = 'prod';
public static function getConfig($key) public static function getConfig($key)
{ {
@ -23,6 +23,7 @@ abstract class AbstractApi
public static function request($uri, $params, $sign) { public static function request($uri, $params, $sign) {
try { try {
Log::info('url:' . $uri, [], 'efps'); Log::info('url:' . $uri, [], 'efps');
Log::info('headers:', self::getXEfpsHeaders($sign), 'efps');
$response = self::getClient()->post($uri, [ $response = self::getClient()->post($uri, [
'json' => $params, 'json' => $params,
'headers' => self::getXEfpsHeaders($sign), 'headers' => self::getXEfpsHeaders($sign),

@ -7,6 +7,50 @@ use App\Helper\StringHelper;
class Api extends AbstractApi class Api extends AbstractApi
{ {
public static function apply()
{
$paper = [
"certificateName" => "李四",
"contactPhone" => "13531231222",
"email" => "test1@test.cn",
"lawyerCertNo" => "430481198104234557",
"lawyerCertType" => "0",
"merchantType" => "3",
"openBank" => "中国银行",
"openingLicenseAccountPhoto" => "https://www.epaylinks.cn/www/wimages/epl_logo.png",
"settleAccount" => "李四",
"settleAccountNo" => "6214830201234567",
"settleAccountType" => "2",
"settleTarget" => "2"
];
$business = [
[
"businessCode" => "WITHDRAW_TO_SETTMENT_DEBIT",
"creditcardsEnabled" => 0,
"refundEnabled" => 1,
"refundFeePer" => 0,
"refundFeeRate" => 0,
"settleCycle" => "D+0",
"stage" => [
[
"amountFrom" => 0,
"feePer" => 50
]
]
]
];
$params = [
'acqSpId' => self::getConfig('customerCode'),
'merchantName' => "测试商户20211202",
'acceptOrder' => 0,
'openAccount' => 1,
'paper' => json_encode($paper, JSON_UNESCAPED_UNICODE),
'business' => $business
];
$sign = Signer::sign(json_encode($params));
return self::request($uri, $params, $sign);
}
public static function register($params) public static function register($params)
{ {
$merId = $params['merId'] ?? ''; $merId = $params['merId'] ?? '';
@ -43,7 +87,7 @@ class Api extends AbstractApi
public static function bindCard($params) public static function bindCard($params)
{ {
$memberId = $params['memberId'] ?? ''; $memberId = self::getConfig('customerCode');
$mchtOrderNo = $params['mchtOrderNo'] ?? StringHelper::generateOrderNo(); $mchtOrderNo = $params['mchtOrderNo'] ?? StringHelper::generateOrderNo();
$userName = $params['userName'] ?? ''; $userName = $params['userName'] ?? '';
$phoneNum = $params['phoneNum'] ?? ''; $phoneNum = $params['phoneNum'] ?? '';
@ -55,7 +99,7 @@ class Api extends AbstractApi
$uri = '/api/txs/protocol/bindCard'; $uri = '/api/txs/protocol/bindCard';
$params = [ $params = [
'version' => '3.0', 'version' => '2.0',
'customerCode' => self::getConfig('customerCode'), 'customerCode' => self::getConfig('customerCode'),
'mchtOrderNo' => $mchtOrderNo, 'mchtOrderNo' => $mchtOrderNo,
'memberId' => $memberId, 'memberId' => $memberId,
@ -67,6 +111,19 @@ class Api extends AbstractApi
'certificatesNo' => Signer::publicEncrypt($certificatesNo), 'certificatesNo' => Signer::publicEncrypt($certificatesNo),
'nonceStr' => StringHelper::getRandomString(32), 'nonceStr' => StringHelper::getRandomString(32),
]; ];
/*$params = [
'version' => '2.0',
'customerCode' => self::getConfig('customerCode'),
'mchtOrderNo' => $mchtOrderNo,
'memberId' => $memberId,
'userName' => $userName,
'phoneNum' => $phoneNum,
'bankCardNo' => $bankCardNo,
'bankCardType' => $bankCardType,
'certificatesType' => '01',
'certificatesNo' => $certificatesNo,
'nonceStr' => StringHelper::getRandomString(32),
];*/
if ($bankCardType == 'credit') { if ($bankCardType == 'credit') {
$params['expired'] = Signer::publicEncrypt($expired); $params['expired'] = Signer::publicEncrypt($expired);
$params['cvn'] = Signer::publicEncrypt($cvn); $params['cvn'] = Signer::publicEncrypt($cvn);
@ -93,6 +150,39 @@ class Api extends AbstractApi
return self::request($uri, $params, $sign); return self::request($uri, $params, $sign);
} }
public static function certifiedPayment($params)
{
$outTradeNo = $params['outTradeNo'] ?? StringHelper::generateOrderNo();
$userName = $params['userName'] ?? '';
$phoneNum = $params['phoneNum'] ?? '';
$bankCardNo = $params['bankCardNo'] ?? '';
$certificatesNo = $params['certificatesNo'] ?? '';
$payAmount = $params['payAmount'] ?? 0;
$payCurrency = 'CNY';
$orderInfo = [];
$orderInfo['Id'] = $outTradeNo;
$orderInfo['businessType'] = '130001';
$orderInfo['goodsList'] = [['name' => 'pay', 'number' => 'one', 'amount' => $payAmount]];
$uri = '/api/txs/pay/CertifiedPayment';
$params = [
'version' => '3.0',
'customerCode' => self::getConfig('customerCode'),
'outTradeNo' => $outTradeNo,
'userName' => Signer::publicEncrypt($userName),
'certificatesType' => '01',
'certificatesNo' => Signer::publicEncrypt($certificatesNo),
'phoneNum' => Signer::publicEncrypt($phoneNum),
'bankCardNo' => Signer::publicEncrypt($bankCardNo),
'payAmount' => $payAmount,
'payCurrency' => $payCurrency,
'orderInfo' => $orderInfo,
'transactionStartTime' => date('YmdHis'),
'nonceStr' => StringHelper::getRandomString(32),
];
$sign = Signer::sign(json_encode($params));
return self::request($uri, $params, $sign);
}
public static function unBindCard($params) public static function unBindCard($params)
{ {
$protocol = $params['protocol'] ?? ''; $protocol = $params['protocol'] ?? '';
@ -157,4 +247,73 @@ class Api extends AbstractApi
$sign = Signer::sign(json_encode($params)); $sign = Signer::sign(json_encode($params));
return self::request($uri, $params, $sign); return self::request($uri, $params, $sign);
} }
public static function refund($params)
{
$uri = '/api/txs/pay/Refund/V2';
$outRefundNo = $params['outRefundNo'] ?? '';
$notifyUrl = $params['notifyUrl'] ?? '';
$outTradeNo = $params['outTradeNo'] ?? '';
$refundAmount = $params['refundAmount'] ?? 0;
$amount = $params['amount'] ?? 0;
$remark = $params['remark'] ?? '';
$params = [
// 'version' => '3.0',
'customerCode' => self::getConfig('customerCode'),
'outRefundNo' => $outRefundNo,
'outTradeNo' => $outTradeNo,
'refundAmount' => $refundAmount,
'amount' => $amount,
'remark' => $remark,
'notifyUrl' => $notifyUrl,
'nonceStr' => StringHelper::getRandomString(32),
];
$sign = Signer::sign(json_encode($params));
return self::request($uri, $params, $sign);
}
public static function refundQuery($params)
{
$uri = '/api/txs/custPay/refundQuery';
$outRefundNo = $params['outRefundNo'] ?? '';
$params = [
// 'version' => '3.0',
'customerCode' => self::getConfig('customerCode'),
'outRefundNo' => $outRefundNo,
'nonceStr' => StringHelper::getRandomString(32),
];
$sign = Signer::sign(json_encode($params));
return self::request($uri, $params, $sign);
}
public static function unifiedPayment()
{
$uri = '/api/txs/pay/UnifiedPayment';
$orderNo = "123456".date('YmdHis');
$client_ip = "127.0.0.1";
$orderInfo = [];
$orderInfo['Id'] = $orderNo;
$orderInfo['businessType'] = '130001';
$orderInfo['goodsList'] = [['name'=>'pay', 'number'=>'one', 'amount'=>1]];
$params = [
'outTradeNo' => $orderNo,
'customerCode' => self::getConfig('customerCode'),
'clientIp' => $client_ip,
'orderInfo' => $orderInfo,
'payCurrency' => 'CNY',
'payAmount' => 10,
'payCurrency' => 'CNY',
'notifyUrl' => 'http://www.baidu.com',
'redirectUrl' => 'http://www.baidu.com',
'transactionStartTime' =>date('YmdHis'),
'nonceStr' => 'pay'.rand(100,999),
'version' => '3.0'
];
$sign = Signer::sign(json_encode($params));
return self::request($uri, $params, $sign);
}
} }

@ -18,9 +18,14 @@ class Result
return $this->data['returnCode'] == '0000'; return $this->data['returnCode'] == '0000';
} }
public function get($key) public function get($key, $default = null)
{ {
return $this->data[$key] ?? null; return $this->data[$key] ?? $default;
}
public function getCode()
{
return $this->data['returnCode'];
} }
public function getMessage() public function getMessage()
@ -28,13 +33,20 @@ class Result
return $this->data['returnMsg']; return $this->data['returnMsg'];
} }
public function getData() public function getData(array $fields = null)
{ {
$data = $this->data; $returnData = [];
unset($data['returnCode']); if (is_array($fields)) {
unset($data['returnMsg']); foreach ($fields as $field) {
unset($data['nonceStr']); $returnData[$field] = $this->data[$field] ?? null;
unset($data['customerCode']); }
return $data; } else {
$returnData = $this->data;
}
unset($returnData['returnCode']);
unset($returnData['returnMsg']);
unset($returnData['nonceStr']);
unset($returnData['customerCode']);
return $returnData;
} }
} }

@ -7,7 +7,7 @@ use App\Helper\StringHelper;
class Signer class Signer
{ {
protected static $env = 'dev'; protected static $env = 'prod';
private static function getConfig($key) private static function getConfig($key)
{ {
@ -61,9 +61,8 @@ class Signer
if (empty($res)) { if (empty($res)) {
throw new BusinessException('RSA公钥错误, 请检查公钥文件格式是否正确'); throw new BusinessException('RSA公钥错误, 请检查公钥文件格式是否正确');
} }
$crypttext = ""; $crypttext = "";
openssl_public_encrypt($data,$crypttext, $res ); openssl_public_encrypt($data,$crypttext, $res);
openssl_free_key($res); openssl_free_key($res);
return(base64_encode($crypttext)); return(base64_encode($crypttext));

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

@ -0,0 +1,67 @@
<?php
declare(strict_types=1);
namespace App\Middleware;
use App\Helper\Redis;
use App\Helper\RedisKey;
use App\Model\RequestLog;
use Hyperf\Context\Context;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class RequestLogMiddleware implements MiddlewareInterface
{
protected ContainerInterface $container;
protected RequestInterface $request;
protected HttpResponse $response;
public function __construct(ContainerInterface $container, HttpResponse $response, RequestInterface $request)
{
$this->container = $container;
$this->response = $response;
$this->request = $request;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$params = $this->request->all();
$appId = $params['app_id'] ?? 0;
$requestLog = new RequestLog();
$requestLog->app_id = $appId;
$requestLog->request_id = $this->generateOrderNo();
$requestLog->request_uri = $this->request->getRequestUri();
$requestLog->request_data = json_encode($params, JSON_UNESCAPED_UNICODE);
$requestLog->request_time = date('Y-m-d H:i:s');
$requestLog->save();
$ctxResponse = Context::get(ResponseInterface::class);
$ctxResponse = $ctxResponse->withHeader('X-Request-Id', $requestLog->request_id);
Context::set(ResponseInterface::class, $ctxResponse);
Context::set('requestLog', $requestLog);
$response = $handler->handle($request);
$requestLog->response_data = (string)$response->getBody();
$requestLog->response_time = date('Y-m-d H:i:s');
return $response;
}
private function generateOrderNo() {
$now = time();
$key = RedisKey::getGenerateRequestIdKey($now);
$incrId = Redis::incr($key);
$incrId = '' . $incrId;
Redis::expire($key, 5*60);
$padLength = 8 - strlen($incrId);
$incrId = str_pad($incrId, $padLength, '0', STR_PAD_LEFT);
return date('YmdHis', $now) . $incrId;
}
}

@ -8,6 +8,7 @@ class Order extends Model
{ {
public const STATUS_PREPARE = 1; public const STATUS_PREPARE = 1;
public const STATUS_WAIT_PAY = 2; public const STATUS_WAIT_PAY = 2;
public const STATUS_APPLY_FAIL = 3;
public const STATUS_PAYED = 6; public const STATUS_PAYED = 6;
public const STATUS_FAILED = 9; public const STATUS_FAILED = 9;

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace App\Model;
class RefundOrder extends Model
{
public const STATUS_PREPARE = 1;
public const STATUS_APPLY_SUCCESS = 2;
public const STATUS_APPLY_FAILED = 3;
public const STATUS_REFUND_SUCCESS = 8;
public const STATUS_REFUND_FAILED = 9;
protected $table = 'refund_orders';
}

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

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

@ -30,9 +30,9 @@ class ApiRequest extends Request
} }
protected function checkSign($params) { protected function checkSign($params) {
/* if ($params['timestamp'] < time() - 600) { if ($params['timestamp'] < time() - 6000) {
throw new BusinessException('请求已过期'); throw new BusinessException('请求已过期');
} */ }
if (!Signer::verify($params, $this->app->app_key)) { if (!Signer::verify($params, $this->app->app_key)) {
throw new BusinessException('验签错误'); throw new BusinessException('验签错误');
} }

@ -0,0 +1,13 @@
<?php
namespace App\Request;
class RefundQueryRequest extends ApiRequest
{
public function rules(): array
{
return [
];
}
}

@ -0,0 +1,13 @@
<?php
namespace App\Request;
class RefundRequest extends ApiRequest
{
public function rules(): array
{
return [
];
}
}

@ -6,6 +6,8 @@ class RegisterRequest extends ApiRequest
{ {
public function rules(): array public function rules(): array
{ {
return []; return [
];
} }
} }

@ -4,16 +4,9 @@ declare(strict_types=1);
namespace App\Service; namespace App\Service;
use App\Exception\BusinessException; use App\Helper\Efps\Result;
use App\Helper\Log;
use App\Helper\OmiPay\Api;
use App\Helper\OmiPay\Result;
use App\Helper\OmiPay\Signer;
use App\Helper\Platform\Notification;
use App\Helper\Platform\Signer as PlatformSigner;
use App\Helper\Redis; use App\Helper\Redis;
use App\Helper\RedisKey; use App\Helper\RedisKey;
use App\Helper\StringHelper;
use App\Model\App; use App\Model\App;
use App\Model\Order; use App\Model\Order;
@ -21,24 +14,31 @@ class PaymentService extends AbstractService
{ {
public function createOrder(App $app, array $params) { public function createOrder(App $app, array $params) {
$order = new Order(); $order = new Order();
$order->merchant_id = $app->merchant_id;
$order->app_id = $app->app_id; $order->app_id = $app->app_id;
$order->order_no = $this->generateOrderNo(); $order->out_order_no = $params['outTradeNo'] ?: '';
$order->out_order_no = $params['out_order_no']; $order->amount = $params['payAmount'] ?: 0;
$order->order_name = $params['order_name']; $order->notify_url = $params['notifyUrl'] ?: '';
$order->amount = $params['amount']; $order->order_info = json_encode($params['orderInfo'] ?: [], JSON_UNESCAPED_UNICODE);
$order->currency = $params['currency'];
$order->redirect_url = $params['redirect_url'];
$order->notify_url = $params['notify_url'];
$order->direct_pay = $params['direct_pay'] ?? 0;
$order->show_pc_pay_url = $params['show_pc_pay_url'] ?? 0;
$order->o_number = $params['o_number'] ?? '';
$order->pos_no = $params['pos_no'] ?? '';
$order->status = Order::STATUS_PREPARE;
$order->save();
return $order; return $order;
} }
public function handlePayResult(Result $result, Order $order) {
if ($result->get('payState') === '00') {
$order->status = Order::STATUS_PAYED;
$order->fee = $result->get('procedureFee', 0);
$order->pay_order_no = $result->get('transactionNo', '');
$order->channel_order_no = $result->get('channelOrder', '');
$order->payed_at = date('Y-m-d H:i:s');
$order->save();
} elseif ($result->get('payState') === '01') {
$order->status = Order::STATUS_FAILED;
$order->error_code = '01';
$order->error_msg = '支付失败';
$order->payed_at = date('Y-m-d H:i:s');
$order->save();
}
}
private function generateOrderNo() { private function generateOrderNo() {
$now = time(); $now = time();
$key = RedisKey::getGenerateOrderNoKey($now); $key = RedisKey::getGenerateOrderNoKey($now);
@ -49,139 +49,4 @@ class PaymentService extends AbstractService
$incrId = str_pad($incrId, $padLength, '0', STR_PAD_LEFT); $incrId = str_pad($incrId, $padLength, '0', STR_PAD_LEFT);
return date('YmdHis', $now) . $incrId; return date('YmdHis', $now) . $incrId;
} }
public function updateOrderResult(Order $order, array $result)
{
if ($result['is_success']) {
$order->pay_order_no = $result['pay_order_no'];
$order->pay_url = $result['pay_url'];
$order->status = Order::STATUS_WAIT_PAY;
} else {
$order->error_code = $result['error_code'];
$order->error_msg = $result['error_msg'];
$order->status = Order::STATUS_FAILED;
}
$order->save();
}
public function jsapiPay(App $app, array $params) {
$order = Order::where('app_id', $app->app_id)->where('out_order_no', $params['out_order_no'])->first();
if ($order) {
throw new BusinessException('订单重复');
}
$order = $this->createOrder($app, $params);
$result = Api::getExchangeRate('AUD', 'CNY');
if (!$result->isSuccess()) {
throw new BusinessException('获取汇率接口失败');
}
$rate = $result->get('rate');
$result = Api::makeJSAPIOrder(
$order->order_name,
$order->order_no,
'AUD',
intval($order->amount / $rate),
'http://146.70.113.165:9501/payment/notify',
'http://146.70.113.165:9501/payment/page?order_no=' . $order->order_no
);
$this->updateOrderResult($order, $result->toArray());
return $order;
}
public function notify($params) {
Log::info('notify:', $params, 'omipay');
if (!Signer::verify($params)) {
return 'SIGN FAIL';
}
if ($params['return_code'] != 'SUCCESS') {
return 'STATUS FAIL';
}
$params = [
'order_no' => $params['out_order_no'],
'cny_amount' => $params['cny_amount'],
'exchange_rage' => $params['exchange_rage'],
];
return $this->handleNotify($params);
}
public function efpsNotify($params) {
Log::info('notify:', $params, 'omipay');
if (!Signer::verify($params)) {
return 'SIGN FAIL';
}
if ($params['return_code'] != 'SUCCESS') {
return 'STATUS FAIL';
}
$params = [
'order_no' => $params['outTradeNo'],
];
return $this->handleNotify($params);
}
private function handleNotify($params) {
$order = Order::where('order_no', $params['order_no'] ?: '')
->where('status', Order::STATUS_WAIT_PAY)
->first();
if (!$order) {
return 'ORDER FAIL';
}
$app = App::where('app_id', $order->app_id)->first();
$order->status = Order::STATUS_PAYED;
$order->payed_at = date('Y-m-d H:i:s');
$order->exchange_rate = $params['exchange_rate'] ?: 1;
$order->cny_amount = $params['cny_amount'] ?: $order->amount;
if (!$order->save()) {
return 'NOTIFY FAIL';
}
Log::info('notifyToOut url:' . $order->notify_url, [], 'omipay');
$result = Notification::post($order->notify_url, $this->buildNotifyParams($order, $app));
Log::info('notifyToOut response:' . $result, [], 'omipay');
if ($result != 'SUCCESS') {
return 'NOTIFY FAIL';
}
return 'SUCCESS';
}
protected function buildNotifyParams(Order $order, App $app) {
$params = [
'app_id' => $order->app_id,
'nonce_str' => StringHelper::getRandomString(32),
'timestamp' => time(),
];
$bizData = [
'code' => 'SUCCESS',
'order_no' => $order->order_no,
'out_order_no' => $order->out_order_no,
'currency' => $order->currency,
'total_amount' => $order->amount,
'order_time' => date('YmdHis', $order->created_at->timestamp),
'pay_time' => date('YmdHis', strtotime($order->payed_at)),
'exchange_rate' => $order->exchange_rate,
'cny_amount' => $order->cny_amount,
];
$params['data'] = json_encode($bizData);
$params['sign'] = PlatformSigner::sign($params, $app->app_key);
Log::info('notifyToOut params:', $params, 'omipay');
return $params;
}
public function unifiedPay(App $app, array $params) {
$order = Order::where('app_id', $app->app_id)->where('out_order_no', $params['out_order_no'])->first();
if ($order) {
throw new BusinessException('订单重复');
}
$order = $this->createOrder($app, $params);
$result = \App\Helper\Efps\Api::unifiedPayment(
$order->order_no,
$order->order_name,
$order->amount,
'http://146.70.113.165:9501/payment/notify',
'http://146.70.113.165:9501/payment/page?order_no=' . $order->order_no
);
$this->updateOrderResult($order, $result->toArray());
return $order;
}
} }

@ -3,7 +3,6 @@
declare(strict_types=1); declare(strict_types=1);
use App\Controller\Payment\NotifyController; use App\Controller\Payment\NotifyController;
use App\Controller\Payment\PageController;
use App\Controller\Payment\PayController; use App\Controller\Payment\PayController;
use Hyperf\HttpServer\Router\Router; use Hyperf\HttpServer\Router\Router;
@ -12,13 +11,18 @@ Router::get('/favicon.ico', function () {
}); });
Router::addGroup('/payment',function () { Router::addGroup('/payment',function () {
Router::post('/jsapi', [PayController::class, 'jsapi']);
Router::post('/register', [PayController::class, 'register']); Router::post('/register', [PayController::class, 'register']);
Router::post('/refund', [PayController::class, 'refund']);
Router::post('/bind-card', [PayController::class, 'bindCard']); Router::post('/bind-card', [PayController::class, 'bindCard']);
Router::post('/bind-card-confirm', [PayController::class, 'bindCardConfirm']); Router::post('/bind-card-confirm', [PayController::class, 'bindCardConfirm']);
Router::post('/un-bind-card', [PayController::class, 'unBindCard']); Router::post('/un-bind-card', [PayController::class, 'unBindCard']);
Router::post('/protocol-pay-pre-request', [PayController::class, 'protocolPayPreRequest']); Router::post('/protocol-pay-pre-request', [PayController::class, 'protocolPayPreRequest']);
Router::post('/protocol-pay-confirm', [PayController::class, 'protocolPayConfirm']); Router::post('/protocol-pay-confirm', [PayController::class, 'protocolPayConfirm']);
Router::get('/page', [PageController::class, 'index']); Router::post('/refund-query', [PayController::class, 'refundQuery']);
Router::addRoute(['GET', 'POST'], '/notify', [NotifyController::class, 'index']); }, ['middleware' => [\App\Middleware\RequestLogMiddleware::class]]);
Router::addGroup('/payment',function () {
Router::addRoute(['GET', 'POST'], '/notify', [NotifyController::class, 'payment']);
Router::addRoute(['GET', 'POST'], '/notify', [NotifyController::class, 'refund']);
}); });

@ -0,0 +1,86 @@
CREATE TABLE `request_logs` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`request_id` varchar(22) not null COMMENT '请求ID',
`app_id` varchar(16) NOT NULL COMMENT '应用ID',
`request_uri` varchar(255) not null COMMENT '请求URI',
`request_data` text default NULL COMMENT '请求内容',
`response_data` text default NULL COMMENT '响应内容',
`request_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`response_time` datetime default NULL,
`third_request_data` text default NULL COMMENT '第三方请求内容',
`third_response_data` text default NULL COMMENT '第三方响应内容',
`third_request_time` datetime default NULL,
`third_response_time` datetime default NULL,
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '订单状态',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `idx_appid` (`app_id`) USING BTREE,
KEY `idx_createdat` (`created_at`) USING BTREE,
UNIQUE KEY `udx_requestid` (`request_id`) USING BTREE,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC;
CREATE TABLE `users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`request_id` varchar(22) not null COMMENT '请求ID',
`app_id` varchar(16) NOT NULL COMMENT '应用ID',
`member_id` varchar(20) not null default '',
`merId` varchar(50) not null default '',
`card_no` varchar(32) not null default '',
`mobile` varchar(15) not null default '',
`card_valid_to` varchar(10) default NULL COMMENT '身份证有效期',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `idx_appid` (`app_id`) USING BTREE,
KEY `idx_memberid` (`member_id`) USING BTREE,
KEY `idx_createdat` (`created_at`) USING BTREE,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC;
CREATE TABLE `orders` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`app_id` varchar(16) NOT NULL COMMENT '应用ID',
`order_info` text default null COMMENT '商品信息',
`out_order_no` varchar(32) NOT NULL COMMENT '外部订单号',
`pay_order_no` varchar(32) NOT NULL DEFAULT '' COMMENT '支付订单号',
`channel_order_no` varchar(32) NOT NULL DEFAULT '' COMMENT '渠道上游订单号',
`amount` int NOT NULL DEFAULT '0' COMMENT '支付金额',
`fee` int NOT NULL DEFAULT '0' COMMENT '手续费',
`redirect_url` varchar(1024) NOT NULL DEFAULT '' COMMENT '跳转地址',
`notify_url` varchar(1024) NOT NULL DEFAULT '' COMMENT '通知地址',
`pay_url` varchar(1024) NOT NULL DEFAULT '' COMMENT '支付地址',
`token` varchar(32) NOT NULL DEFAULT '',
`protocol` varchar(16) NOT NULL DEFAULT '',
`payed_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '支付时间',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '订单状态',
`error_code` varchar(32) NOT NULL DEFAULT '' COMMENT '错误码',
`error_msg` varchar(255) NOT NULL DEFAULT '' COMMENT '错误信息',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `idx_outorderno` (`out_order_no`) USING BTREE,
KEY `idx_token` (`token`) USING BTREE,
KEY `idx_protocol` (`protocol`) USING BTREE,
KEY `idx_createdat` (`created_at`) USING BTREE,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='订单表';
CREATE TABLE `refund_orders` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`app_id` varchar(16) NOT NULL COMMENT '应用ID',
`out_order_no` varchar(32) NOT NULL COMMENT '外部订单号',
`out_refund_order_no` varchar(32) NOT NULL COMMENT '外部退款订单号',
`order_amount` int NOT NULL DEFAULT '0' COMMENT '订单金额',
`refund_amount` int NOT NULL DEFAULT '0' COMMENT '退款金额',
`fee` int NOT NULL DEFAULT '0' COMMENT '手续费',
`notify_url` varchar(1024) NOT NULL DEFAULT '' COMMENT '通知地址',
`remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注',
`refunded_at` datetime default NULL COMMENT '退款时间',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '订单状态',
`error_code` varchar(32) NOT NULL DEFAULT '' COMMENT '错误码',
`error_msg` varchar(255) NOT NULL DEFAULT '' COMMENT '错误信息',
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `idx_refundorderno` (`refund_order_no`) USING BTREE,
KEY `idx_createdat` (`created_at`) USING BTREE,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='退款订单表';

@ -0,0 +1,527 @@
<?php
header('Content-type:text/html;charset=UTF-8');
class Efalipay {
//测试环境主扫接口路径
protected $gateway = 'http://test-efps.epaylinks.cn/api/txs/pay/NativePayment';
protected $gateway1 = 'http://test-efps.epaylinks.cn/api/txs/pay/UnifiedPayment';
protected $gateway2 = 'http://test-efps.epaylinks.cn//api/txs/pay/unionPayMent';
protected $bindCardUrl = 'https://efps.epaylinks.cn/api/txs/protocol/bindCard';
// protected $bindCardUrl = 'http://test-efps.epaylinks.cn/api/txs/protocol/bindCard';
//测试环境单笔提现接口路径
protected $withdrawalToCard = 'https://efps.epaylinks.cn/api/txs/pay/withdrawalToCard';
//进件
protected $apply_url = 'http://test-efps.epaylinks.cn/api/cust/SP/Merchant/apply';
//生产环境接口路径
//protected $gateway = 'https://efps.epaylinks.cn/api/txs/pay/NativePayment';
//私钥文件路径
public $rsaPrivateKeyFilePath = "/Users/liaojinling/Projects/php/payment/certs/prod/user.pfx";
//易票联公钥
public $publicKeyFilePath = "/Users/liaojinling/Projects/php/payment/certs/prod/efps.cer";
// public $rsaPrivateKeyFilePath = "/Users/liaojinling/Projects/php/payment/certs/dev/user.pfx";
//易票联公钥
// public $publicKeyFilePath = "/Users/liaojinling/Projects/php/payment/certs/dev/efps.cer";
//证书序列号
// public $sign_no='562265003122220003';
public $sign_no = '562276004021027002';
//证书密码
// public $password='123456';
public $password='iUixTxtl8N2Ntlx1LqZ';
//编码格式
public $charset = "UTF-8";
public $signType = "RSA2";
//商户号
protected $config = array(
// 'customer_code' => '562265003122220',
'customer_code' => '562276004021027',
'notify_url' => 'http://www.baidu.com',
'return_url' => 'http://www.baidu.com'
);
public function check() {
if (!$this->config['customer_code'] ) {
E("支付设置有误!");
}
return true;
}
// 测试主扫
public function buildRequestForm() {
$orderNo = "123456".date('YmdHis');
echo 'orderNo: '.$orderNo;
echo PHP_EOL;
$client_ip = "127.0.0.1";
if (getenv('HTTP_CLIENT_IP')) {
$client_ip = getenv('HTTP_CLIENT_IP');
} elseif (getenv('HTTP_X_FORWARDED_FOR')) {
$client_ip = getenv('HTTP_X_FORWARDED_FOR');
} elseif (getenv('REMOTE_ADDR')) {
$client_ip = getenv('REMOTE_ADDR');
} else {
$client_ip = $_SERVER['REMOTE_ADDR'];
}
$orderInfo=array();
$orderInfo['Id'] = $orderNo;
$orderInfo['businessType'] = '130001';
$orderInfo['goodsList'] = array(array('name'=>'pay','number'=>'one','amount'=>1));
$param = array(
'outTradeNo' => $orderNo,
'customerCode' => $this->config['customer_code'],
'clientIp' => $client_ip,
'orderInfo' => $orderInfo,
'payMethod' => 7,
'payAmount' => 10,
'payCurrency' => 'CNY',
'channelType' =>'02',
'notifyUrl' =>$this->config['notify_url'],
'redirectUrl' =>$this->config['return_url'],
'transactionStartTime' =>date('YmdHis'),
'nonceStr' => 'pay'.rand(100,999),
'version' => '3.0'
);
$sign = $this->sign(json_encode($param));
echo 'request: '.json_encode($param);
echo PHP_EOL .'sign: '.$sign;
$request = $this->http_post_json($this->gateway,json_encode($param),$sign);
if($request && $request[0] == 200){
echo PHP_EOL . 'response: ';
return $request[1];
}else{
print_r($request);
exit;
}
exit;
}
// 统一下单
public function buildRequestForm1() {
$orderNo = "123456".date('YmdHis');
echo 'orderNo: '.$orderNo;
echo PHP_EOL;
$client_ip = "127.0.0.1";
if (getenv('HTTP_CLIENT_IP')) {
$client_ip = getenv('HTTP_CLIENT_IP');
} elseif (getenv('HTTP_X_FORWARDED_FOR')) {
$client_ip = getenv('HTTP_X_FORWARDED_FOR');
} elseif (getenv('REMOTE_ADDR')) {
$client_ip = getenv('REMOTE_ADDR');
} else {
$client_ip = $_SERVER['REMOTE_ADDR'];
}
$orderInfo = array();
$orderInfo['Id'] = $orderNo;
$orderInfo['businessType'] = '130001';
$orderInfo['goodsList'] = array(array('name'=>'pay','number'=>'one','amount'=>1));
$param = array(
'outTradeNo' => $orderNo,
'customerCode' => $this->config['customer_code'],
'clientIp' => $client_ip,
'orderInfo' => $orderInfo,
'payCurrency' => 'CNY',
// 'payMethod' => 7,
'payAmount' => 10,
'payCurrency' => 'CNY',
// 'channelType' =>'02',
'notifyUrl' =>$this->config['notify_url'],
'redirectUrl' =>$this->config['return_url'],
'transactionStartTime' =>date('YmdHis'),
'nonceStr' => 'pay'.rand(100,999),
'version' => '3.0'
);
$sign = $this->sign(json_encode($param));
echo 'request: '.json_encode($param);
echo PHP_EOL .'sign: '.$sign;
$request = $this->http_post_json($this->gateway1, json_encode($param),$sign);
if($request && $request[0] == 200){
echo PHP_EOL . 'response: ';
return $request[1];
}else{
print_r($request);
exit;
}
exit;
}
// 统一下单
public function buildRequestForm2() {
$orderNo = "123456".date('YmdHis');
echo 'orderNo: '.$orderNo;
echo PHP_EOL;
$client_ip = "127.0.0.1";
if (getenv('HTTP_CLIENT_IP')) {
$client_ip = getenv('HTTP_CLIENT_IP');
} elseif (getenv('HTTP_X_FORWARDED_FOR')) {
$client_ip = getenv('HTTP_X_FORWARDED_FOR');
} elseif (getenv('REMOTE_ADDR')) {
$client_ip = getenv('REMOTE_ADDR');
} else {
$client_ip = $_SERVER['REMOTE_ADDR'];
}
$orderInfo = array();
$orderInfo['Id'] = $orderNo;
$orderInfo['businessType'] = '130001';
$orderInfo['goodsList'] = array(array('name'=>'pay','number'=>'one','amount'=>1));
$param = array(
'outTradeNo' => $orderNo,
'customerCode' => $this->config['customer_code'],
'clientIp' => $client_ip,
'orderInfo' => $orderInfo,
'payCurrency' => 'CNY',
'payAmount' => 10,
'payCurrency' => 'CNY',
'bankCardType' =>'debit',
'notifyUrl' =>$this->config['notify_url'],
'frontUrl' =>$this->config['return_url'],
'transactionStartTime' =>date('YmdHis'),
'nonceStr' => 'pay'.rand(100,999),
'version' => '3.0'
);
$sign = $this->sign(json_encode($param));
echo 'request: '.json_encode($param);
echo PHP_EOL .'sign: '.$sign;
$request = $this->http_post_json($this->gateway2, json_encode($param),$sign);
if($request && $request[0] == 200){
echo PHP_EOL . 'response: ';
return $request[1];
}else{
print_r($request);
exit;
}
exit;
}
//测试单笔提现
public function withDraw() {
$orderNo = "tx123".date('YmdHis');
echo '订单号:'.$orderNo;
echo '<br>';
$param = array(
'outTradeNo' => $orderNo,
'customerCode' => $this->config['customer_code'],
'amount' => 10,
'bankUserName' =>$this->public_encrypt('张三'),
'bankCardNo' => $this->public_encrypt('6214858888883338'),
'bankName' => '招商银行',
'bankAccountType' =>'2',
'payCurrency' => 'CNY',
'notifyUrl' =>$this->config['notify_url'],
'nonceStr' => 'pay'.rand(100,999),
);
$sign = $this->sign(json_encode($param));
echo 'request: '.json_encode($param);
echo '<br>sign: '.$sign;
$request = $this->http_post_json($this->withdrawalToCard,json_encode($param),$sign);
if($request && $request[0] == 200){
echo '<br>'.'response: ';
return $request[1];
}else{
print_r($request);
exit;
}
exit;
}
public function bindCard() {
$orderNo = "tx123".date('YmdHis');
echo '订单号:'.$orderNo;
echo '<br>';
$param = array(
'version' => '3.0',
'mchtOrderNo' => time() . rand(1000, 9999),
'customerCode' => $this->config['customer_code'],
'memberId' => $this->config['customer_code'],
'userName' => $this->public_encrypt('zs'),
'phoneNum' => $this->public_encrypt('18760419185'),
'bankCardNo' => $this->public_encrypt('6214835911385365'),
'bankCardType' => 'debit',
'certificatesType' => '01',
'certificatesNo' => $this->public_encrypt('350824199001105476'),
'nonceStr' => 'pay'.rand(100,999),
);
$sign = $this->sign(json_encode($param));
echo 'request: '.json_encode($param);
echo '<br>sign: '.$sign;
$request = $this->http_post_json($this->bindCardUrl,json_encode($param),$sign);
if($request && $request[0] == 200){
echo '<br>'.'response: ';
return $request[1];
}else{
print_r($request);
exit;
}
exit;
}
//进件
//发起进件
public function apply(){
$paper = '{"certificateName":"李四","contactPhone":"13531231222","email":"test1@test.cn","lawyerCertNo":"430481198104234557","lawyerCertType":"0","merchantType":"3","openBank":"中国银行","openingLicenseAccountPhoto":"https://www.epaylinks.cn/www/wimages/epl_logo.png","settleAccount":"李四","settleAccountNo":"6214830201234567","settleAccountType":"2","settleTarget":"2"}';
$business = array(
array(
"businessCode"=>"WITHDRAW_TO_SETTMENT_DEBIT",
"creditcardsEnabled"=>0,
"refundEnabled"=>1,
"refundFeePer"=>0,
"refundFeeRate"=>0,
"settleCycle"=>"D+0",
"stage"=>array(
array(
"amountFrom"=>0,
"feePer"=>50
)
)
)
);
$param =array(
'acqSpId' => $this->config['customer_code'],
'merchantName' => "测试商户20211202",
'acceptOrder' => 0,
'openAccount' => 1,
'paper' => $paper,
'business' =>$business
);
$sign = $this->sign(json_encode($param));
echo json_encode($param);
$res = $this->http_post_json($this->apply_url,json_encode($param),$sign);
var_dump($res);
die;
}
public function generateSign($params) {
return $this->sign($this->getSignContent($params));
}
public function rsaSign($params) {
return $this->sign($this->getSignContent($params));
}
protected function getSignContent($params) {
ksort($params);
$stringToBeSigned = "";
$i = 0;
foreach ($params as $k => $v) {
if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {
// 转换成目标字符集
$v = $this->characet($v, $this->charset);
if ($i == 0) {
$stringToBeSigned .= "$k" . "=" . "$v";
} else {
$stringToBeSigned .= "&" . "$k" . "=" . "$v";
}
$i++;
}
}
unset ($k, $v);
return $stringToBeSigned;
}
protected function sign($data) {
$certs = array();
openssl_pkcs12_read(file_get_contents($this->rsaPrivateKeyFilePath), $certs, $this->password); //其中password为你的证书密码
($certs) or die('请检查RSA私钥配置');
openssl_sign($data, $sign, $certs['pkey'],OPENSSL_ALGO_SHA256);
$sign = base64_encode($sign);
return $sign;
}
/**
* 校验$value是否非空
* if not set ,return true;
* if is null , return true;
**/
protected function checkEmpty($value) {
if (!isset($value))
return true;
if ($value === null)
return true;
if (trim($value) === "")
return true;
return false;
}
public function rsaCheckV2($params, $rsaPublicKeyFilePath,$sign) {
//$sign = $params['sign'];
//$params['sign'] = null;
return $this->verify($params, $sign, $rsaPublicKeyFilePath);
}
//使用易票联公钥验签 //返回的验签字段有中文需要加JSON_UNESCAPED_UNICODE才能验签通过
//$data2 = json_encode($data, JSON_UNESCAPED_UNICODE);
function verify($data, $sign, $rsaPublicKeyFilePath) {
//读取公钥文件
$pubKey = file_get_contents($this->publicKeyFilePath);
$res = openssl_get_publickey($pubKey);
($res) or die('RSA公钥错误。请检查公钥文件格式是否正确');
//调用openssl内置方法验签返回bool值
$result = (bool)openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256);
if(!$this->checkEmpty($this->publicKeyFilePath)) {
//释放资源
openssl_free_key($res);
}
return $result;
}
//使用易票联公钥加密
function public_encrypt($data)
{
return $data;
//读取公钥文件
$pubKey = file_get_contents($this->publicKeyFilePath);
$res = openssl_get_publickey($pubKey);
($res) or die('RSA公钥错误。请检查公钥文件格式是否正确');
$crypttext = "";
openssl_public_encrypt($data,$crypttext, $res);
if(!$this->checkEmpty($this->publicKeyFilePath)) {
//释放资源
openssl_free_key($res);
}
return(base64_encode($crypttext));
}
/**
* 转换字符集编码
* @param $data
* @param $targetCharset
* @return string
*/
function characet($data, $targetCharset) {
if (!empty($data)) {
$fileType = $this->charset;
if (strcasecmp($fileType, $targetCharset) != 0) {
$data = mb_convert_encoding($data, $targetCharset);
// $data = iconv($fileType, $targetCharset.'//IGNORE', $data);
}
}
return $data;
}
protected function getParam($para) {
$arg = "";
while (list ($key, $val) = each($para)) {
$arg.=$key . "=" . $val . "&";
}
//去掉最后一个&字符
$arg = substr($arg, 0, -1);
return $arg;
}
/**
* 获取远程服务器ATN结果,验证返回URL
* @param $notify_id
* @return
* 验证结果集:
* invalid命令参数不对 出现这个错误请检测返回处理中partner和key是否为空
* true 返回正确信息
* false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟
*/
protected function getResponse2($Params) {
$veryfy_url = $this->gateway . "?" . $Params;
$responseTxt = $this->fsockOpen($veryfy_url);
return $responseTxt;
}
protected function http_post_json($url, $jsonStr,$sign)
{
$ch = curl_init();
$headers = array(
'Content-Type: application/json; charset=utf-8',
'Content-Length: ' . strlen($jsonStr),
'x-efps-sign-no:'.$this->sign_no,
'x-efps-sign-type:SHA256withRSA',
'x-efps-sign:'.$sign,
'x-efps-timestamp:'.date('YmdHis'),
);
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_SSL_VERIFYPEER, false); // 跳过检查
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 跳过检查
//curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
return array($httpCode, $response);
}
}
$efalipay = new Efalipay();
echo $efalipay->bindCard();
Loading…
Cancel
Save