123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- <?php
- namespace crmeb\services;
- use crmeb\utils\Hook;
- use think\facade\Log;
- use think\facade\Route as Url;
- use Alipay\EasySDK\Kernel\Config;
- use Alipay\EasySDK\Kernel\Factory;
- use crmeb\exceptions\PayException;
- use app\services\pay\PayNotifyServices;
- use Alipay\EasySDK\Kernel\Util\ResponseChecker;
- use AlibabaCloud\Tea\Tea;
- class AliPayService
- {
-
- protected $config = [
- 'appId' => '',
- 'merchantPrivateKey' => '',
- 'alipayPublicKey' => '',
- 'notifyUrl' => '',
- 'encryptKey' => '',
- ];
-
- protected $response;
-
- protected $authCode;
-
- protected static $instance;
-
- protected function __construct(array $config = [])
- {
- if (!$config) {
- $alipay = SystemConfigService::more(['ali_pay_appid', 'alipay_merchant_private_key', 'alipay_public_key', 'site_url']);
- $config = [
- 'appId' => $alipay['ali_pay_appid'] ?? '',
- 'merchantPrivateKey' => $alipay['alipay_merchant_private_key'] ?? '',
- 'alipayPublicKey' => $alipay['alipay_public_key'] ?? '',
- 'notifyUrl' => ($alipay['site_url'] ?? '') . Url::buildUrl('/api/pay/notify/alipay'),
- ];
- }
- $this->config = array_merge($this->config, $config);
- $this->initialize();
- $this->response = new ResponseChecker();
- }
-
- public static function instance(array $config = [])
- {
- if (is_null(self::$instance)) {
- self::$instance = new static($config);
- }
- return self::$instance;
- }
-
- public static function isAliPayAuthCode(string $authCode)
- {
- return preg_match('/^[0-9]{16,24}$/', $authCode) && in_array(substr($authCode, 0, 2), ['25', '26', '27', '28', '29', '30']);
- }
-
- protected function initialize()
- {
- Factory::setOptions($this->getOptions());
- }
-
- protected function getOptions()
- {
- $options = new Config();
- $options->protocol = 'https';
- $options->gatewayHost = 'openapi.alipay.com';
- $options->signType = 'RSA2';
- $options->appId = $this->config['appId'];
-
- $options->merchantPrivateKey = $this->config['merchantPrivateKey'];
-
- $options->alipayPublicKey = $this->config['alipayPublicKey'];
-
- $options->notifyUrl = $this->config['notifyUrl'];
-
- if ($this->config['encryptKey']) {
- $options->encryptKey = $this->config['encryptKey'];
- }
- Tea::config(['verify' => false]);
- return $options;
- }
-
- public function microPay(string $authCode, string $title, string $orderId, string $totalAmount, string $passbackParams)
- {
- $title = trim($title);
- try {
- $result = Factory::payment()->faceToFace()->optional('passback_params', $passbackParams)->pay($title, $orderId, $totalAmount, $authCode);
- if ($this->response->success($result)) {
- $response = $result->toMap();
- return [
- 'paid' => $response['code'] === '10000' ? 1 : 0,
- 'message' => $response['sub_msg'] ?? '支付成功',
- 'payInfo' => $response
- ];
- } else {
- throw new PayException('失败原因:' . $result->msg . ',' . $result->subMsg);
- }
- } catch (\Exception $e) {
- throw new PayException($e->getMessage());
- }
- }
-
- public function create(string $title, string $orderId, string $totalAmount, string $passbackParams, string $quitUrl = '', string $siteUrl = '', bool $isCode = false)
- {
- $title = trim($title);
- try {
- if ($isCode) {
-
- $result = Factory::payment()->faceToFace()->optional('passback_params', $passbackParams)->precreate($title, $orderId, $totalAmount);
- } else if (request()->isApp()) {
-
- $result = Factory::payment()->app()->optional('passback_params', $passbackParams)->pay($title, $orderId, $totalAmount);
- } else {
-
- $result = Factory::payment()->wap()->optional('passback_params', $passbackParams)->pay($title, $orderId, $totalAmount, $quitUrl, $siteUrl);
- }
- if ($this->response->success($result)) {
- return isset($result->body) ? $result->body : $result;
- } else {
- throw new PayException('失败原因:' . $result->msg . ',' . $result->subMsg);
- }
- } catch (\Exception $e) {
- throw new PayException($e->getMessage());
- }
- }
-
- public function refund(string $outTradeNo, string $totalAmount, string $refund_id)
- {
- try {
- $result = Factory::payment()->common()->refund($outTradeNo, $totalAmount, $refund_id);
- if ($this->response->success($result)) {
- return $result;
- } else {
- throw new PayException('失败原因:' . $result->msg . ',' . $result->subMsg);
- }
- } catch (\Exception $e) {
- throw new PayException($e->getMessage());
- }
- }
-
- public function queryRefund(string $outTradeNo, string $outRequestNo)
- {
- try {
- $result = Factory::payment()->common()->queryRefund($outTradeNo, $outRequestNo);
- if ($this->response->success($result)) {
- return $result;
- } else {
- throw new PayException('失败原因:' . $result->msg . ',' . $result->subMsg);
- }
- } catch (\Exception $e) {
- throw new PayException($e->getMessage());
- }
- }
-
- public static function handleNotify()
- {
- return self::instance()->notify(function ($notify) {
- if (isset($notify->out_trade_no)) {
- if (isset($notify->attach) && $notify->attach) {
- if (($count = strpos($notify->out_trade_no, '_')) !== false) {
- $notify->trade_no = $notify->out_trade_no;
- $notify->out_trade_no = substr($notify->out_trade_no, $count + 1);
- }
- return (new Hook(PayNotifyServices::class, 'aliyun'))->listen($notify->attach, $notify->out_trade_no, $notify->trade_no);
- }
- return false;
- }
- });
- }
-
- public function notify(callable $notifyFn)
- {
- app()->request->filter(['trim']);
- $paramInfo = app()->request->postMore([
- ['gmt_create', ''],
- ['charset', ''],
- ['seller_email', ''],
- ['subject', ''],
- ['sign', ''],
- ['buyer_id', ''],
- ['invoice_amount', ''],
- ['notify_id', ''],
- ['fund_bill_list', ''],
- ['notify_type', ''],
- ['trade_status', ''],
- ['receipt_amount', ''],
- ['buyer_pay_amount', ''],
- ['app_id', ''],
- ['seller_id', ''],
- ['sign_type', ''],
- ['gmt_payment', ''],
- ['notify_time', ''],
- ['passback_params', ''],
- ['version', ''],
- ['out_trade_no', ''],
- ['total_amount', ''],
- ['trade_no', ''],
- ['auth_app_id', ''],
- ['buyer_logon_id', ''],
- ['point_amount', ''],
- ], false, false);
-
- $postOrder['out_trade_no'] = $paramInfo['out_trade_no'] ?? '';
-
- $postOrder['trade_no'] = $paramInfo['trade_no'] ?? '';
-
- $postOrder['trade_status'] = $paramInfo['trade_status'] ?? '';
-
- $postOrder['attach'] = isset($paramInfo['passback_params']) ? urldecode($paramInfo['passback_params']) : '';
- if (in_array($postOrder['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED']) && $this->verifyNotify($paramInfo)) {
- try {
- if ($notifyFn((object)$postOrder)) {
- return 'success';
- }
- } catch (\Exception $e) {
- Log::error('支付宝异步会回调成功,执行函数错误。错误单号:' . $postOrder['out_trade_no']);
- }
- }
- return 'fail';
- }
-
- protected function verifyNotify(array $param)
- {
- try {
- return Factory::payment()->common()->verifyNotify($param);
- } catch (\Exception $e) {
- Log::error('支付宝回调成功,验签发生错误,错误原因:' . $e->getMessage());
- }
- return false;
- }
- }
|