efps-version
elf 2 years ago
parent e704371b1d
commit c53bf7df08

@ -4,10 +4,12 @@ declare(strict_types=1);
namespace App\Command; namespace App\Command;
use App\Helper\Efps\Api;
use App\Helper\Signer; use App\Helper\Signer;
use App\Service\AppService; use App\Service\AppService;
use App\Service\MerchantService; use App\Service\MerchantService;
use App\Service\PaymentService; use App\Service\PaymentService;
use Hyperf\Command\Annotation\Command;
use Hyperf\Command\Command as HyperfCommand; use Hyperf\Command\Command as HyperfCommand;
use Hyperf\Contract\ContainerInterface; use Hyperf\Contract\ContainerInterface;
@ -38,6 +40,29 @@ class JinlingCommand extends HyperfCommand
public function handle(): void public function handle(): void
{ {
/*Api::register([
'merId' => "100", // 562238003185933
'backUrl' => 'http://www.baidu.com',
'certificateName' => '测试',
'lawyerCertType' => 0,
'lawyerCertNo' => '430481198104234557',
'lawyerCertPhotoFront' => 'http://5b0988e595225.cdn.sohucs.com/images/20191031/e6a31c2611f042bbbfd39297243437a7.png',
'lawyerCertPhotoBack' => 'http://5b0988e595225.cdn.sohucs.com/images/20191031/e6a31c2611f042bbbfd39297243437a7.png',
'certificateTo' => '20500211',
'contactPhone' => '18888888888',
'accountType' => 3,
'canDownType' => '01',
]);*/
Api::bindCard([
'memberId' => '562238003185933',
'mchtOrderNo' => time() . rand(1000, 9999),
'userName' => '测试',
'phoneNum' => '18888888888',
'bankCardNo' => '6214835911385365',
'bankCardType' => 'debit',
'certificatesNo' => '430481198104234557',
]);
return;
echo \App\Helper\Efps\Signer::sign('sss'); echo \App\Helper\Efps\Signer::sign('sss');
$sm3 = new \OneSm\Sm3(); $sm3 = new \OneSm\Sm3();

@ -4,7 +4,15 @@ declare(strict_types=1);
namespace App\Controller\Payment; namespace App\Controller\Payment;
use App\Exception\BusinessException;
use App\Helper\Efps\Api;
use App\Request\BindCardConfirmRequest;
use App\Request\BindCardRequest;
use App\Request\JsapiPayRequest; use App\Request\JsapiPayRequest;
use App\Request\ProtocolPayConfirmRequest;
use App\Request\ProtocolPayPreRequest;
use App\Request\RegisterRequest;
use App\Request\UnBindCardRequest;
use Hyperf\HttpServer\Contract\RequestInterface; use Hyperf\HttpServer\Contract\RequestInterface;
use App\Service\PaymentService; use App\Service\PaymentService;
@ -27,13 +35,63 @@ class PayController extends AbstractController
]); ]);
} }
public function unified() public function register(RequestInterface $request)
{ {
$payRequest = new JsapiPayRequest($request->all()); $req = new RegisterRequest($request->all());
$order = $this->paymentService->js($payRequest->getApp(), $payRequest->getData()); $result = Api::register($req->getData());
return $this->success([ if (!$result->isSuccess()) {
'pay_url' => $order->pay_url, throw new BusinessException($result->getMessage());
'order_no' => $order->order_no, }
]); return $this->success($result->getData());
}
public function bindCard(RequestInterface $request)
{
$req = new BindCardRequest($request->all());
$result = Api::bindCard($req->getData());
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
return $this->success($result->getData());
}
public function bindCardConfirm(RequestInterface $request)
{
$req = new BindCardConfirmRequest($request->all());
$result = Api::bindCardConfirm($req->getData());
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
return $this->success($result->getData());
}
public function unBindCard(RequestInterface $request)
{
$req = new UnBindCardRequest($request->all());
$result = Api::unBindCard($req->getData());
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
return $this->success($result->getData());
}
public function protocolPayPreRequest(RequestInterface $request)
{
$req = new ProtocolPayPreRequest($request->all());
$result = Api::protocolPayPre($req->getData());
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
return $this->success($result->getData());
}
public function protocolPayConfirm(RequestInterface $request)
{
$req = new ProtocolPayConfirmRequest($request->all());
$result = Api::protocolPayConfirm($req->getData());
if (!$result->isSuccess()) {
throw new BusinessException($result->getMessage());
}
return $this->success($result->getData());
} }
} }

@ -12,12 +12,20 @@ abstract class AbstractApi
{ {
protected static $client; protected static $client;
public static function request(AbstractRequest $request) { protected static $env = 'dev';
$params = $request->getParams();
public static function getConfig($key)
{
$config = Config::get(self::$env);
return $config ? ($config[$key] ?? null) : null;
}
public static function request($uri, $params, $sign) {
try { try {
Log::info('url:' . $request->getUrl(), [], 'omipay'); Log::info('url:' . $uri, [], 'efps');
$response = self::getClient()->post($request->getUrl(), [ $response = self::getClient()->post($uri, [
'query' => $params 'json' => $params,
'headers' => self::getXEfpsHeaders($sign),
]); ]);
Log::info('request:', $params, 'efps'); Log::info('request:', $params, 'efps');
$body = (string)$response->getBody(); $body = (string)$response->getBody();
@ -43,11 +51,8 @@ abstract class AbstractApi
protected static function getClient(): Client { protected static function getClient(): Client {
if (!self::$client) { if (!self::$client) {
self::$client = new Client([ self::$client = new Client([
'base_uri' => Config::get('base_url'), 'base_uri' => self::getConfig('baseUrl'),
'handler' => HandlerStack::create(new CoroutineHandler()), 'handler' => HandlerStack::create(new CoroutineHandler()),
'headers' => [
'Content-Type' => 'application/json',
],
'timeout' => 5, 'timeout' => 5,
'swoole' => [ 'swoole' => [
'timeout' => 10, 'timeout' => 10,
@ -58,15 +63,13 @@ abstract class AbstractApi
return self::$client; return self::$client;
} }
protected static function getHeaders($sign, $encKey, $timestamp) protected static function getXEfpsHeaders($sign)
{ {
return [ return [
'x-efps-sign-no' => '', 'x-efps-sign-no' => self::getConfig('signNo'),
'x-efps-sign-type' => 'RSAwithSHA256', 'x-efps-sign-type' => 'SHA256withRSA',
'x-efps-sign' => $sign, 'x-efps-sign' => $sign,
'x-efps-timestamp' => $timestamp, 'x-efps-timestamp' => date('YmdHis')
'x-efps-version' => '2.0',
'x-efps-enc-key' => $encKey,
]; ];
} }
} }

@ -7,18 +7,154 @@ use App\Helper\StringHelper;
class Api extends AbstractApi class Api extends AbstractApi
{ {
public static function unifiedPayment($outTradeNo, $orderInfo, $payAmount, $notifyUrl, $redirectUrl) public static function register($params)
{ {
$request = new UnifiedPaymentRequest(); $merId = $params['merId'] ?? '';
$request->setVersion('3.0'); $backUrl = $params['backUrl'] ?? '';
$request->setOutTradeNo($outTradeNo); $certificateName = $params['certificateName'] ?? '';
$request->setOrderInfo($orderInfo); $lawyerCertType = $params['lawyerCertType'] ?? 0;
$request->setPayAmount($payAmount); $lawyerCertNo = $params['lawyerCertNo'] ?? '';
$request->setNotifyUrl($notifyUrl); $lawyerCertPhotoFront = $params['lawyerCertPhotoFront'] ?? '';
$request->setRedirectUrl($redirectUrl); $lawyerCertPhotoBack = $params['lawyerCertPhotoBack'] ?? '';
$request->setTransactionStartTime(date('YmdHis')); $certificateTo = $params['certificateTo'] ?? '';
$request->setAreaInfo([]); $contactPhone = $params['contactPhone'] ?? '';
$request->setNonceStr(StringHelper::getRandomString(32)); $accountType = $params['accountType'] ?? 3;
return self::request($request); $canDownType = $params['canDownType'] ?? '01';
$uri = '/api/cust/SP/Personal/apply';
$params = [
'version' => '3.0',
'acqSpId' => self::getConfig('customerCode'),
'merId' => $merId,
'backUrl' => $backUrl,
'certificateName' => $certificateName,
'lawyerCertType' => $lawyerCertType,
'lawyerCertNo' => $lawyerCertNo,
'lawyerCertPhotoFront' => $lawyerCertPhotoFront,
'lawyerCertPhotoBack' => $lawyerCertPhotoBack,
'certificateTo' => $certificateTo,
'contactPhone' => $contactPhone,
'accountType' => $accountType,
'canDownType' => $canDownType,
];
$sign = Signer::sign(json_encode($params));
return self::request($uri, $params, $sign);
}
public static function bindCard($params)
{
$memberId = $params['memberId'] ?? '';
$mchtOrderNo = $params['mchtOrderNo'] ?? StringHelper::generateOrderNo();
$userName = $params['userName'] ?? '';
$phoneNum = $params['phoneNum'] ?? '';
$bankCardNo = $params['bankCardNo'] ?? '';
$bankCardType = $params['bankCardType'] ?? '';
$certificatesNo = $params['certificatesNo'] ?? '';
$expired = $params['expired'] ?? '';
$cvn = $params['cvn'] ?? '';
$uri = '/api/txs/protocol/bindCard';
$params = [
'version' => '3.0',
'customerCode' => self::getConfig('customerCode'),
'mchtOrderNo' => $mchtOrderNo,
'memberId' => $memberId,
'userName' => Signer::publicEncrypt($userName),
'phoneNum' => Signer::publicEncrypt($phoneNum),
'bankCardNo' => Signer::publicEncrypt($bankCardNo),
'bankCardType' => $bankCardType,
'certificatesType' => '01',
'certificatesNo' => Signer::publicEncrypt($certificatesNo),
'nonceStr' => StringHelper::getRandomString(32),
];
if ($bankCardType == 'credit') {
$params['expired'] = Signer::publicEncrypt($expired);
$params['cvn'] = Signer::publicEncrypt($cvn);
}
$sign = Signer::sign(json_encode($params));
return self::request($uri, $params, $sign);
}
public static function bindCardConfirm($params)
{
$smsNo = $params['smsNo'] ?? '';
$smsCode = $params['smsCode'] ?? '';
$memberId = $params['memberId'] ?? '';
$uri = '/api/txs/protocol/bindCardConfirm';
$params = [
'version' => '3.0',
'customerCode' => self::getConfig('customerCode'),
'smsNo' => $smsNo,
'memberId' => $memberId,
'smsCode' => $smsCode,
'nonceStr' => StringHelper::getRandomString(32),
];
$sign = Signer::sign(json_encode($params));
return self::request($uri, $params, $sign);
}
public static function unBindCard($params)
{
$protocol = $params['protocol'] ?? '';
$memberId = $params['memberId'] ?? '';
$uri = '/api/txs/protocol/unBindCard';
$params = [
'version' => '3.0',
'customerCode' => self::getConfig('customerCode'),
'protocol' => $protocol,
'memberId' => $memberId,
'nonceStr' => StringHelper::getRandomString(32),
];
$sign = Signer::sign(json_encode($params));
return self::request($uri, $params, $sign);
}
public static function protocolPayPre($params)
{
$outTradeNo = $params['outTradeNo'] ?? StringHelper::generateOrderNo();
$protocol = $params['protocol'] ?? '';
$smsNo = $params['smsNo'] ?? '';
$smsCode = $params['smsCode'] ?? '';
$payAmount = $params['payAmount'] ?? 0;
$orderInfo = [];
$orderInfo['Id'] = $outTradeNo;
$orderInfo['businessType'] = '130001';
$orderInfo['goodsList'] = [['name' => 'pay', 'number' => 'one', 'amount' => $$payAmount]];
$uri = '/api/txs/protocol/protocolPayPre';
$params = [
'version' => '3.0',
'customerCode' => self::getConfig('customerCode'),
'outTradeNo' => $outTradeNo,
'protocol' => $protocol,
// 'smsNo' => $smsNo,
// 'smsCode' => $smsCode,
'orderInfo' => $orderInfo,
'payAmount' => $payAmount,
'payCurrency' => 'CNY',
'isInstalments' => 0,
'transactionStartTime' => date('YmdHis'),
'nonceStr' => StringHelper::getRandomString(32),
];
$sign = Signer::sign(json_encode($params));
return self::request($uri, $params, $sign);
}
public static function protocolPayConfirm($params)
{
$smsCode = $params['smsCode'] ?? '';
$protocol = $params['protocol'] ?? '';
$token = $params['token'] ?? '';
$uri = '/api/txs/protocol/protocolPayConfirm';
$params = [
'version' => '3.0',
'customerCode' => self::getConfig('customerCode'),
'token' => $token,
'protocol' => $protocol,
'smsCode' => $smsCode,
'nonceStr' => StringHelper::getRandomString(32),
];
$sign = Signer::sign(json_encode($params));
return self::request($uri, $params, $sign);
} }
} }

@ -4,42 +4,26 @@ namespace App\Helper\Efps;
class Config class Config
{ {
private static $params = [ private static array $params = [
'app_id' => '', 'dev' => [
'secret_key' => 'cea6f34bea8640dea91fd8b7a926a9a5', 'customerCode' => '562265003122220',
'base_url' => 'https://efps.epylinks.cn', 'signNo' => '562265003122220003',
'public_key' => '', 'baseUrl' => 'http://test-efps.epaylinks.cn',
'private_key' => '-----BEGIN PRIVATE KEY----- 'privateKeyFilePath' => BASE_PATH . '/certs/dev/user.pfx',
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC7ibPHSAc2glW5 'publicKeyFilePath' => BASE_PATH . '/certs/dev/efps.cer',
ZHKhSJR8SHTwkAlN9H0KhiX+NzxuZirUd8VhyPKFcOeSvf+lRo8P7EHd2Hsfly39 'privateKeyPassword' => '123456',
SuTZv4LUqsU0ODw0bXuC7ys1P6kctUc8Pi5Zg7l2FpVQZIwxkszevuYmjSQ7NTA7 ],
GAS/4pZX6C4yyDObQBV5nmSnhGXzKk/z3c6O829jgVlbFMAKKF//Q4TBiooOeZpY 'prod' => [
rgkGtaZSN50puM+WDn7S/ETwZELBi2jRDqg6bJKYsCVPHW/yPdnMS0BMQcDhJsI8 'customerCode' => '562276004021027',
3BwNvBiJQo4yZ0RmLw3SmIjcThieo74fcHH0Le0TFZRD1dl2OOgPO4lCFxFV6BM0 'signNo' => '562276004021027002',
wARseqddAgMBAAECggEBAIXZb2XBQ9ykw3hRd/si6U+XC1eTBgEMiZ5URpOdatVE 'baseUrl' => 'https://efps.epaylinks.cn',
uDby0P7MxEN3ZOB4GRkmNf9gWVZ0JtRSO3G33YSISmFtDNkLdfTZWzkFaKpVqGaj 'privateKeyFilePath' => BASE_PATH . '/certs/prod/user.pfx',
/5bArqYW/OyKi8FYMjNDmlM0nuFPBVf4y1ax+tnVaAaP4UE/YI3i/DDUWvSw627U 'publicKeyFilePath' => BASE_PATH . '/certs/prod/efps.cer',
PqTAAEEeJi624UsVIVLbiWQkaztiutPQYTxONYKt1xcI3OUUBETvRy621czlWIhO 'privateKeyPassword' => 'iUixTxtl8N2Ntlx1LqZ',
I/bbThawyu4xLrN8eDa6KSeD+LvC3u5IumroDCgoKrOSuY3GesWN7rPm1uVTMCDe ]
CacQkc2Nx28PiiRFj8XiVzSdHFIEiNopLpHlIv6U+6ECgYEA9DlBhqZoX8pxc2Nq
tm+MLXeY16lr9W23em+51TIEgBnMSne2+yY4+ni0b4x0buFXgH7bR2mSoHzVDvjJ
nYA82YlYtKI6QiSUsKU0WDfzPWqUrTfkt2JUjIwBBFN4vY070Kcu3bV7CsoXLg2E
E6ThtRn7VCQ/+8R/uyU+kuWDXxkCgYEAxJS008rYLfDl6Mqt4gBWdX0OOmck+jQ7
nT5c/sPggi222z3ka+RGWRERbG40EXiP6xL0AEQ5GJhYITKODnd8XmeOQyMnlFwP
uD33cjhwdOhH2EYTW7KUumo1Dc1ZfPThNk3SnVLvTPBD9cli4vbsU73YhvQp/BDA
3aw3RhscBuUCgYEA5AJ4nL/L/nLBDNuqi30FQIXCGsbAVjkC7bpVoye5b+emBXhT
S5NZ6u66dtKI+eREj2DgVIHKNS+Wsw2vHe7V4LsMKEi1X39LmsgCYMKLw7E38aiX
TmbtTPKBGIrd1QqA58LOTIvcviwDDCnuP3DWkQAa12momuPP5OdWzkqdJjECgYEA
w1kbURRUO2MWtX0jymCXim1ZhEQXhOP/EcV1WF6CbhrLiZc5tNXF6qCBdgUVjP8H
1YyiGNmy+3P4sBSzAkFOv+mcf68hl9bccDRz/3eCmUpyisMoXYlbLtx4GF0mPnyC
iRpQ37IYx5ZDkq4rrGvAcX9I+uMMDccAQcjvrKUn9tkCgYAcx/Usx7dsJyq9qt0x
nPryFkGoDjUg4U5WFvN4d4et4oMDAvA4iFkPxdLlGokYtLC0cEsAmKEqVKVs/Zfa
FyqcOZZSfgy6c90YmbXTmEHIayR05IxVRrL0T+/CGtnYGsNPLGNCSL9eU7zxA+QW
HeJnufFo3VmRzqOQcqrLfi/scQ==
-----END PRIVATE KEY-----'
]; ];
public static function get($key) { public static function get($env): ?array {
return self::$params[$key] ?: null; return self::$params[$env] ?: null;
} }
} }

@ -1,32 +0,0 @@
<?php
namespace App\Helper\Efps\Request;
use App\Helper\Efps\Config;
class AbstractRequest
{
protected $uri;
protected $method;
protected $_params = [];
public function getUrl() {
return Config::get('base_url') . $this->uri;
}
public function getParams() {
return $this->_params;
}
public function __get($name)
{
return $this->_params[$name];
}
public function __set($name, $value)
{
$this->_params[$name] = $value;
}
}

@ -1,216 +0,0 @@
<?php
namespace App\Helper\Efps\Request;
class UnifiedPaymentRequest extends AbstractRequest
{
protected $uri = '/api/txs/pay/UnifiedPayment';
/**
* @param mixed $version
*/
public function setVersion($version): void
{
$this->version = $version;
}
/**
* @param mixed $outTradeNo
*/
public function setOutTradeNo($outTradeNo): void
{
$this->outTradeNo = $outTradeNo;
}
/**
* @param mixed $customerCode
*/
public function setCustomerCode($customerCode): void
{
$this->customerCode = $customerCode;
}
/**
* @param mixed $clientIp
*/
public function setClientIp($clientIp): void
{
$this->clientIp = $clientIp;
}
/**
* @param mixed $orderInfo
*/
public function setOrderInfo($orderInfo): void
{
$this->orderInfo = $orderInfo;
}
/**
* @param mixed $payAmount
*/
public function setPayAmount($payAmount): void
{
$this->payAmount = $payAmount;
}
/**
* @param mixed $payCurrency
*/
public function setPayCurrency($payCurrency): void
{
$this->payCurrency = $payCurrency;
}
/**
* @param mixed $noCreditCards
*/
public function setNoCreditCards($noCreditCards): void
{
$this->noCreditCards = $noCreditCards;
}
/**
* @param mixed $notifyUrl
*/
public function setNotifyUrl($notifyUrl): void
{
$this->notifyUrl = $notifyUrl;
}
/**
* @param mixed $redirectUrl
*/
public function setRedirectUrl($redirectUrl): void
{
$this->redirectUrl = $redirectUrl;
}
/**
* @param mixed $attachData
*/
public function setAttachData($attachData): void
{
$this->attachData = $attachData;
}
/**
* @param mixed $transactionStartTime
*/
public function setTransactionStartTime($transactionStartTime): void
{
$this->transactionStartTime = $transactionStartTime;
}
/**
* @param mixed $transactionEndTime
*/
public function setTransactionEndTime($transactionEndTime): void
{
$this->transactionEndTime = $transactionEndTime;
}
/**
* @param mixed $payMethod
*/
public function setPayMethod($payMethod): void
{
$this->payMethod = $payMethod;
}
/**
* @param mixed $subAppId
*/
public function setSubAppId($subAppId): void
{
$this->subAppId = $subAppId;
}
/**
* @param mixed $channelMchtNo
*/
public function setChannelMchtNo($channelMchtNo): void
{
$this->channelMchtNo = $channelMchtNo;
}
/**
* @param mixed $enablePayChannels
*/
public function setEnablePayChannels($enablePayChannels): void
{
$this->enablePayChannels = $enablePayChannels;
}
/**
* @param mixed $instalmentsNum
*/
public function setInstalmentsNum($instalmentsNum): void
{
$this->instalmentsNum = $instalmentsNum;
}
/**
* @param mixed $storeId
*/
public function setStoreId($storeId): void
{
$this->storeId = $storeId;
}
/**
* @param mixed $alipayStoreId
*/
public function setAlipayStoreId($alipayStoreId): void
{
$this->alipayStoreId = $alipayStoreId;
}
/**
* @param mixed $extUserInfo
*/
public function setExtUserInfo($extUserInfo): void
{
$this->extUserInfo = $extUserInfo;
}
/**
* @param mixed $terminalInfo
*/
public function setTerminalInfo($terminalInfo): void
{
$this->terminalInfo = $terminalInfo;
}
/**
* @param mixed $areaInfo
*/
public function setAreaInfo($areaInfo): void
{
$this->areaInfo = $areaInfo;
}
/**
* @param mixed $extendParams
*/
public function setExtendParams($extendParams): void
{
$this->extendParams = $extendParams;
}
/**
* @param mixed $coupons
*/
public function setCoupons($coupons): void
{
$this->coupons = $coupons;
}
/**
* @param mixed $nonceStr
*/
public function setNonceStr($nonceStr): void
{
$this->nonceStr = $nonceStr;
}
}

@ -23,16 +23,18 @@ class Result
return $this->data[$key] ?? null; return $this->data[$key] ?? null;
} }
public function toArray() public function getMessage()
{ {
$data = []; return $this->data['returnMsg'];
if ($this->isSuccess()) {
$data['is_success'] = true;
$data['pay_url'] = $this->get('pay_url');
} else {
$data['error_code'] = $this->get('error_code');
$data['error_msg'] = $this->get('error_msg');
} }
public function getData()
{
$data = $this->data;
unset($data['returnCode']);
unset($data['returnMsg']);
unset($data['nonceStr']);
unset($data['customerCode']);
return $data; return $data;
} }
} }

@ -2,82 +2,70 @@
namespace App\Helper\Efps; namespace App\Helper\Efps;
use App\Exception\BusinessException;
use App\Helper\StringHelper; use App\Helper\StringHelper;
class Signer class Signer
{ {
private static $privateKey = '-----BEGIN PRIVATE KEY----- protected static $env = 'dev';
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC7ibPHSAc2glW5
ZHKhSJR8SHTwkAlN9H0KhiX+NzxuZirUd8VhyPKFcOeSvf+lRo8P7EHd2Hsfly39 private static function getConfig($key)
SuTZv4LUqsU0ODw0bXuC7ys1P6kctUc8Pi5Zg7l2FpVQZIwxkszevuYmjSQ7NTA7
GAS/4pZX6C4yyDObQBV5nmSnhGXzKk/z3c6O829jgVlbFMAKKF//Q4TBiooOeZpY
rgkGtaZSN50puM+WDn7S/ETwZELBi2jRDqg6bJKYsCVPHW/yPdnMS0BMQcDhJsI8
3BwNvBiJQo4yZ0RmLw3SmIjcThieo74fcHH0Le0TFZRD1dl2OOgPO4lCFxFV6BM0
wARseqddAgMBAAECggEBAIXZb2XBQ9ykw3hRd/si6U+XC1eTBgEMiZ5URpOdatVE
uDby0P7MxEN3ZOB4GRkmNf9gWVZ0JtRSO3G33YSISmFtDNkLdfTZWzkFaKpVqGaj
/5bArqYW/OyKi8FYMjNDmlM0nuFPBVf4y1ax+tnVaAaP4UE/YI3i/DDUWvSw627U
PqTAAEEeJi624UsVIVLbiWQkaztiutPQYTxONYKt1xcI3OUUBETvRy621czlWIhO
I/bbThawyu4xLrN8eDa6KSeD+LvC3u5IumroDCgoKrOSuY3GesWN7rPm1uVTMCDe
CacQkc2Nx28PiiRFj8XiVzSdHFIEiNopLpHlIv6U+6ECgYEA9DlBhqZoX8pxc2Nq
tm+MLXeY16lr9W23em+51TIEgBnMSne2+yY4+ni0b4x0buFXgH7bR2mSoHzVDvjJ
nYA82YlYtKI6QiSUsKU0WDfzPWqUrTfkt2JUjIwBBFN4vY070Kcu3bV7CsoXLg2E
E6ThtRn7VCQ/+8R/uyU+kuWDXxkCgYEAxJS008rYLfDl6Mqt4gBWdX0OOmck+jQ7
nT5c/sPggi222z3ka+RGWRERbG40EXiP6xL0AEQ5GJhYITKODnd8XmeOQyMnlFwP
uD33cjhwdOhH2EYTW7KUumo1Dc1ZfPThNk3SnVLvTPBD9cli4vbsU73YhvQp/BDA
3aw3RhscBuUCgYEA5AJ4nL/L/nLBDNuqi30FQIXCGsbAVjkC7bpVoye5b+emBXhT
S5NZ6u66dtKI+eREj2DgVIHKNS+Wsw2vHe7V4LsMKEi1X39LmsgCYMKLw7E38aiX
TmbtTPKBGIrd1QqA58LOTIvcviwDDCnuP3DWkQAa12momuPP5OdWzkqdJjECgYEA
w1kbURRUO2MWtX0jymCXim1ZhEQXhOP/EcV1WF6CbhrLiZc5tNXF6qCBdgUVjP8H
1YyiGNmy+3P4sBSzAkFOv+mcf68hl9bccDRz/3eCmUpyisMoXYlbLtx4GF0mPnyC
iRpQ37IYx5ZDkq4rrGvAcX9I+uMMDccAQcjvrKUn9tkCgYAcx/Usx7dsJyq9qt0x
nPryFkGoDjUg4U5WFvN4d4et4oMDAvA4iFkPxdLlGokYtLC0cEsAmKEqVKVs/Zfa
FyqcOZZSfgy6c90YmbXTmEHIayR05IxVRrL0T+/CGtnYGsNPLGNCSL9eU7zxA+QW
HeJnufFo3VmRzqOQcqrLfi/scQ==
-----END PRIVATE KEY-----';
private static $publicKey = '';
public static function sign($params, $timestamp, $version = 2)
{ {
ksort($params); $config = Config::get(self::$env);
$paramRows = []; return $config ? ($config[$key] ?? null) : null;
foreach ($params as $key => $value) {
$paramRows[] = $key . '=' . $value;
} }
$queryString = implode('&', $paramRows);
if ($version == 1) { public static function sign($data) {
return self::rsaWithSHA256Sign($queryString, self::$privateKey); $certs = [];
openssl_pkcs12_read(
file_get_contents(self::getConfig('privateKeyFilePath')),
$certs,
self::getConfig('privateKeyPassword')
); //其中password为你的证书密码
if (empty($certs)) {
throw new BusinessException('请检查RSA私钥配置');
} }
$randomKey = StringHelper::getRandomString(32);
$encKey = self::rsaWithSHA256Encypt($randomKey, self::$publicKey); openssl_sign($data, $sign, $certs['pkey'],OPENSSL_ALGO_SHA256);
$sm3 = new \OneSm\Sm3(); $sign = base64_encode($sign);
$signBody = $sm3->sign($queryString . $timestamp . $encKey); return $sign;
return self::rsaWithSHA256Sign($signBody, self::$privateKey);
} }
public static function rsaWithSHA256Sign($content, $privateKey) public static function verify($data, $sign) {
{
$key = openssl_get_privatekey($privateKey); //读取公钥文件
// openssl_private_encrypt($content, $signature, $privateKey, OPENSSL_PKCS1_PADDING); $pubKey = file_get_contents(self::getConfig('publicKeyFilePath'));
openssl_sign($content, $signature, $key, OPENSSL_ALGO_SHA256);
openssl_free_key($key); $res = openssl_get_publickey($pubKey);
return base64_encode($signature);
if (empty($res)) {
throw new BusinessException('RSA公钥错误, 请检查公钥文件格式是否正确');
} }
//调用openssl内置方法验签返回bool值
public static function rsaWithSHA256Encypt($content, $publicKey) $result = (bool)openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256);
{ // 释放资源
$key = openssl_get_publickey($publicKey); openssl_free_key($res);
openssl_public_decrypt($content, $signature, $key, OPENSSL_PKCS1_PADDING);
openssl_free_key($key); return $result;
return base64_encode($signature);
} }
public function verify($content, $sign, $publicKey) public static function publicEncrypt($data)
{ {
$key = openssl_get_publickey($publicKey); //读取公钥文件
$ok = openssl_verify($content, base64_decode($sign), $key, 'SHA256'); $pubKey = file_get_contents(self::getConfig('publicKeyFilePath'));
openssl_free_key($key);
return $ok; $res = openssl_get_publickey($pubKey);
if (empty($res)) {
throw new BusinessException('RSA公钥错误, 请检查公钥文件格式是否正确');
} }
$crypttext = "";
openssl_public_encrypt($data,$crypttext, $res );
openssl_free_key($res);
return(base64_encode($crypttext));
}
} }

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

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

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

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

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

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

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

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID0jCCArqgAwIBAgIJAP7Hut/02gF6MA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
BAYTAkdaMQswCQYDVQQIDAJHRDELMAkGA1UEBwwCR1oxDTALBgNVBAoMBEVQQVkx
EjAQBgNVBAsMCWVwYXlsaW5rczENMAsGA1UEAwwEeWlscjEjMCEGCSqGSIb3DQEJ
ARYUeWlsaXJlbkBlcGF5bGlua3MuY24wHhcNMjMwNDEzMDE1MDM5WhcNMzMwNDEw
MDE1MDM5WjB+MQswCQYDVQQGEwJHWjELMAkGA1UECAwCR0QxCzAJBgNVBAcMAkda
MQ0wCwYDVQQKDARFUEFZMRIwEAYDVQQLDAllcGF5bGlua3MxDTALBgNVBAMMBHlp
bHIxIzAhBgkqhkiG9w0BCQEWFHlpbGlyZW5AZXBheWxpbmtzLmNuMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1SL1lt41Phow3aZKQhB0zXNCX4DNqMkr
88/auTe/Lq7llBNYWtPJeABg6K+8JHAs6L90yzQN3mUU3k4gKFLCJPQEIlK9sPKA
AJQnDAs+3PUucgl1QCJnmeSRQKQCGfFjmsGOn+deyV/Lx4gHd3ytpErUDM1iEfen
YHQACuGlRK9G7w90V0UnF7YJca5FCB/wzL3QjqcQC6Z9e/bYXQES7fQH8vX+ajBr
gvi9nMVjFugsZk5sLkwGeYuY4/HMuUWQ8wW+Fvu8cJKtb48sqTl1eTPMhKPwgrgY
EB+RIBA4Ls/gF4/7/dQJA18xFS60Dbn7LS6IP6OTkO9BP4k+qi0kLQIDAQABo1Mw
UTAdBgNVHQ4EFgQUZlpKcM3zf5c8fed6tWnRVVQfC4AwHwYDVR0jBBgwFoAUZlpK
cM3zf5c8fed6tWnRVVQfC4AwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsF
AAOCAQEAyIhFS5AzMVNYXqjRxkKIgdEFt3DXVWermW6L/w0S774ebflQT7fabZhP
+NirUB9VP2hM4axZEhXSXYBeRMw9ahs/It0OrBNbmH+N4bIUVLdGeMoGpjjV5vvd
OV5Tagna7hhaK0F3iBOnjDiO17INxMiRx9yt7n41ml+4VLAbaLY1l0CGouNmrkzT
15CxLnB29m0Xq3V+YsLfDV5ohUNtbFX3NrBUXSHUUf5n8YWqJWTQl2TkeMoYAJbs
WSdkZGNB5KGDUORRPjabpEs2+0+uGHgVr3Llxc3rEVgLSX0wFe1ytLbIW0ibmQV+
tpiZYSSfN6lzzX9NnQk3zGLv+UfIag==
-----END CERTIFICATE-----

Binary file not shown.

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID0jCCArqgAwIBAgIJAP7Hut/02gF6MA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
BAYTAkdaMQswCQYDVQQIDAJHRDELMAkGA1UEBwwCR1oxDTALBgNVBAoMBEVQQVkx
EjAQBgNVBAsMCWVwYXlsaW5rczENMAsGA1UEAwwEeWlscjEjMCEGCSqGSIb3DQEJ
ARYUeWlsaXJlbkBlcGF5bGlua3MuY24wHhcNMjMwNDEzMDE1MDM5WhcNMzMwNDEw
MDE1MDM5WjB+MQswCQYDVQQGEwJHWjELMAkGA1UECAwCR0QxCzAJBgNVBAcMAkda
MQ0wCwYDVQQKDARFUEFZMRIwEAYDVQQLDAllcGF5bGlua3MxDTALBgNVBAMMBHlp
bHIxIzAhBgkqhkiG9w0BCQEWFHlpbGlyZW5AZXBheWxpbmtzLmNuMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1SL1lt41Phow3aZKQhB0zXNCX4DNqMkr
88/auTe/Lq7llBNYWtPJeABg6K+8JHAs6L90yzQN3mUU3k4gKFLCJPQEIlK9sPKA
AJQnDAs+3PUucgl1QCJnmeSRQKQCGfFjmsGOn+deyV/Lx4gHd3ytpErUDM1iEfen
YHQACuGlRK9G7w90V0UnF7YJca5FCB/wzL3QjqcQC6Z9e/bYXQES7fQH8vX+ajBr
gvi9nMVjFugsZk5sLkwGeYuY4/HMuUWQ8wW+Fvu8cJKtb48sqTl1eTPMhKPwgrgY
EB+RIBA4Ls/gF4/7/dQJA18xFS60Dbn7LS6IP6OTkO9BP4k+qi0kLQIDAQABo1Mw
UTAdBgNVHQ4EFgQUZlpKcM3zf5c8fed6tWnRVVQfC4AwHwYDVR0jBBgwFoAUZlpK
cM3zf5c8fed6tWnRVVQfC4AwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsF
AAOCAQEAyIhFS5AzMVNYXqjRxkKIgdEFt3DXVWermW6L/w0S774ebflQT7fabZhP
+NirUB9VP2hM4axZEhXSXYBeRMw9ahs/It0OrBNbmH+N4bIUVLdGeMoGpjjV5vvd
OV5Tagna7hhaK0F3iBOnjDiO17INxMiRx9yt7n41ml+4VLAbaLY1l0CGouNmrkzT
15CxLnB29m0Xq3V+YsLfDV5ohUNtbFX3NrBUXSHUUf5n8YWqJWTQl2TkeMoYAJbs
WSdkZGNB5KGDUORRPjabpEs2+0+uGHgVr3Llxc3rEVgLSX0wFe1ytLbIW0ibmQV+
tpiZYSSfN6lzzX9NnQk3zGLv+UfIag==
-----END CERTIFICATE-----

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDlzCCAn+gAwIBAgIUbeOvQXeD5BI4jOTpkUv+70RShvcwDQYJKoZIhvcNAQEL
BQAwWzELMAkGA1UEBhMCQ04xDzANBgNVBAgMBkZ1SmlhbjEPMA0GA1UEBwwGWGlh
TWVuMQ4wDAYDVQQKDAVGdXN1bzEMMAoGA1UECwwDY3d4MQwwCgYDVQQDDANjd3gw
HhcNMjMwNTIyMTQ0MjE4WhcNMzMwNTE5MTQ0MjE4WjBbMQswCQYDVQQGEwJDTjEP
MA0GA1UECAwGRnVKaWFuMQ8wDQYDVQQHDAZYaWFNZW4xDjAMBgNVBAoMBUZ1c3Vv
MQwwCgYDVQQLDANjd3gxDDAKBgNVBAMMA2N3eDCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBALuJs8dIBzaCVblkcqFIlHxIdPCQCU30fQqGJf43PG5mKtR3
xWHI8oVw55K9/6VGjw/sQd3Yex+XLf1K5Nm/gtSqxTQ4PDRte4LvKzU/qRy1Rzw+
LlmDuXYWlVBkjDGSzN6+5iaNJDs1MDsYBL/illfoLjLIM5tAFXmeZKeEZfMqT/Pd
zo7zb2OBWVsUwAooX/9DhMGKig55mliuCQa1plI3nSm4z5YOftL8RPBkQsGLaNEO
qDpskpiwJU8db/I92cxLQExBwOEmwjzcHA28GIlCjjJnRGYvDdKYiNxOGJ6jvh9w
cfQt7RMVlEPV2XY46A87iUIXEVXoEzTABGx6p10CAwEAAaNTMFEwHQYDVR0OBBYE
FF9zWOWuZ8LYknEJf5MfrFIP/HGqMB8GA1UdIwQYMBaAFF9zWOWuZ8LYknEJf5Mf
rFIP/HGqMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEC4LnW7
J69MLiUt2ypYjSmhyauJixINdG6r53JUaKw2d0Dd73PmYmU1lyTFJEOOFhK3w9hU
5cgExxcn1AZdb2vtzwETv7dgRJHbxVVhl6JsPvFw82b9ALGgFbq5d2Kyewa5eLBh
2IiThu19BBbvs0H6MjP7Kim1fx0z/aIK9F5b9zJxFw35t35Jz1cziXbpS2ha2HDS
0EKrqESbX37iZ8jzO4sMb5hPDZ+BuugFOmZbbPoHqqKZw1l9EWO4Lm36PezMTpwP
1dGRRjcxRWcZ9k4zbdmxzNGL+yxSjl4kvTDjr8ygQmTGBrH7f2z/5LaU48IeNZtl
eEM6UAUyVJDtLl4=
-----END CERTIFICATE-----

Binary file not shown.

@ -13,6 +13,12 @@ Router::get('/favicon.ico', function () {
Router::addGroup('/payment',function () { Router::addGroup('/payment',function () {
Router::post('/jsapi', [PayController::class, 'jsapi']); Router::post('/jsapi', [PayController::class, 'jsapi']);
Router::post('/register', [PayController::class, 'register']);
Router::post('/bind-card', [PayController::class, 'bindCard']);
Router::post('/bind-card-confirm', [PayController::class, 'bindCardConfirm']);
Router::post('/un-bind-card', [PayController::class, 'unBindCard']);
Router::post('/protocol-pay-pre-request', [PayController::class, 'protocolPayPreRequest']);
Router::post('/protocol-pay-confirm', [PayController::class, 'protocolPayConfirm']);
Router::get('/page', [PageController::class, 'index']); Router::get('/page', [PageController::class, 'index']);
Router::addRoute(['GET', 'POST'], '/notify', [NotifyController::class, 'index']); Router::addRoute(['GET', 'POST'], '/notify', [NotifyController::class, 'index']);
}); });

Loading…
Cancel
Save