| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- <?php
- namespace addons\Alitopay\common\services;
- use addons\Alitopay\common\enums\AlitoapyEnum;
- use addons\Alitopay\common\jdk\alipay\AlipayConfig;
- use addons\Alitopay\common\jdk\alipay\AopCertClient;
- use addons\Alitopay\common\jdk\alipay\AopClient;
- use addons\Alitopay\common\jdk\alipay\request\AlipayFundTransUniTransferRequest;
- use common\helpers\ArrayHelper;
- use common\helpers\FormatHelper;
- use Exception;
- use Omnipay\Alipay\AopPageGateway;
- use Omnipay\Omnipay;
- use RuntimeException;
- use Yii;
- class AlipayService extends BaseService
- {
- const URI = '/alitopay/notify/alipay';
- protected $sand_box = false;
- /**
- * @var AopPageGateway|null
- */
- protected $aop = null;
- public function setSandBox(bool $boolean)
- {
- $this->sand_box = $boolean;
- }
- /**
- * 创建支付宝AOP
- *
- * @return AopPageGateway
- */
- public function createAop(array $setting = [])
- {
- if (empty($setting) && empty($this->mall_id)) throw new \Exception('未定义Mall-Id');
- if (empty($setting)) $setting = (new SettingService($this->mall_id))->getSetting();
- /**
- * @var \Omnipay\Alipay\AopPageGateway
- */
- $this->aop = Omnipay::create('Alipay_AopWap');
- $this->aop->setSignType('RSA2'); // RSA/RSA2/MD5. Use certificate mode must set RSA2
- $this->aop->setAppId($setting['app_id']);
- $this->aop->setPrivateKey(trim($setting['private_key']));
- $this->aop->setAlipayPublicKey(trim($setting['alipay_public_key']));
- // 回调地址
- $this->aop->setNotifyUrl(
- $this->getNotifyUrl()
- );
- // 设置沙盒
- $this->sand_box && $this->aop->sandbox();
- return $this->aop;
- }
- /**
- * 单笔转账
- *
- * @param float $money
- * @param string $name
- * @param string $account
- * @param string $order_sn
- * @param string $payee_type
- * @param string $remark
- * @return array|string
- */
- public function transfer(
- float $money,
- string $name,
- string $account,
- string $order_sn,
- string $remark = AlitoapyEnum::DEF_REMARK,
- string $payee_type = 'ALIPAY_LOGON_ID'
- )
- {
- $data = [
- 'out_biz_no' => $order_sn,
- 'trans_amount' => $money,
- 'order_title' => $remark,
- 'remark' => $remark,
- 'payee_info' => [
- 'identity_type' => $payee_type,
- 'identity' => $account,
- 'name' => $name,
- ]
- ];
- try {
- return $this->alipayFundTransUniTransfer($data);
- } catch (Exception $e) {
- Yii::$app->custom->logs(FormatHelper::exception($e, '支付宝代付提现失败'), compact('data'));
- return ['code' => -1, 'sub_msg' => '系统异常', 'msg' => '系统异常'];
- }
- }
- private function isCreatedAop()
- {
- if ($this->aop === null) $this->createAop();
- }
- /**
- * 获取回调地址
- *
- * @return string
- */
- private function getNotifyUrl()
- {
- return Yii::$app->services->setting->platform->get('system.api_url') . static::URI;
- }
- public function getAopClient(){
- if (empty($setting) && empty($this->mall_id)) throw new \Exception('未定义Mall-Id');
- if (empty($setting)) $setting = (new SettingService($this->mall_id))->getSetting();
- $aop = new AopClient();
- $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
- $aop->appId = $setting['app_id'];
- $aop->rsaPrivateKey = trim($setting['private_key']);
- $aop->alipayrsaPublicKey=trim($setting['alipay_public_key']);
- $aop->apiVersion = '1.0';
- $aop->signType = 'RSA2';
- $aop->postCharset='UTF-8';
- $aop->format='json';
- return $aop;
- }
- /**
- * 获取配置
- *
- * 这个方法是复制上面的getAopClient
- * 因为上面的方法是有缺失的,但是不删,因为或许其他地方有用到
- * 所以针对“申请电子回单”的功能,用这个新方法,且这个“申请电子回单”的功能按照原来的代码,本就一直就用不了的
- * 此新方法与原方法的区别是:获取的配置rsaPrivateKey、alipayrsaPublicKey,是用全局的支付宝配置,并不是用“支付宝代付”的配置
- *
- * @throws \Exception 当未定义Mall-Id时抛出异常
- * @return AopClient 初始化的支付宝客户端对象
- */
- public function getAopClientMall()
- {
- if (empty($setting) && empty($this->mall_id)) throw new \Exception('未定义Mall-Id');
- if (empty($setting)) $setting = (new SettingService($this->mall_id))->getSetting();
- $settingMall = \Yii::$app->services->setting->mall->get($this->mall_id, 'pay');
- $settingMall = json_decode($settingMall['alipay'], true);
- $aop = new AopClient();
- $aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
- $aop->appId = $settingMall['alipay_app_id'];
- $aop->rsaPrivateKey = trim($settingMall['alipay_private_key']);
- $aop->alipayrsaPublicKey = trim($settingMall['alipay_public_key']);
- $aop->apiVersion = '1.0';
- $aop->signType = 'RSA2';
- $aop->postCharset = 'UTF-8';
- $aop->format = 'json';
- return $aop;
- }
- /**
- * 获取 "alipay.fund.trans.uni.transfer(单笔转账接口)" 配置
- *
- * @param array $setting
- *
- * @return AlipayConfig
- * @throws Exception
- */
- protected function getAlipayConfig(array $setting = [])
- {
- if (empty($setting) && empty($this->mall_id)) throw new Exception('未定义Mall-Id');
- if (empty($setting)) $setting = (new SettingService($this->mall_id))->getSetting();
- $alipayConfig = new AlipayConfig();
- $alipayConfig->setPrivateKey($setting['private_key']);
- $alipayConfig->setServerUrl('https://openapi.alipay.com/gateway.do');
- $alipayConfig->setAppId($setting['app_id']);
- $alipayConfig->setCharset('UTF-8');
- $alipayConfig->setSignType('RSA2');
- $alipayConfig->setFormat('json');
- $alipayConfig->setAppCertContent($setting['app_cert']);
- $alipayConfig->setAlipayPublicCertContent($setting['alipay_public_key']);
- $alipayConfig->setRootCertContent($setting['root_cert']);
- return $alipayConfig;
- }
- /**
- * 调用 alipay.fund.trans.uni.transfer(单笔转账接口)
- *
- * @param array $data
- *
- * @return array
- * @throws Exception
- */
- protected function alipayFundTransUniTransfer(array $data = []): array
- {
- // 初始化SDK
- $alipayClient = new AopCertClient($this->getAlipayConfig());
- // 构造请求参数以调用接口
- $request = new AlipayFundTransUniTransferRequest();
-
- // 设置描述特定的业务场景
- !isset($data['biz_scene']) && $data['biz_scene'] = "DIRECT_TRANSFER";
- // 设置业务产品码
- !isset($data['product_code']) && $data['product_code'] = "TRANS_ACCOUNT_NO_PWD";
- $request->setBizContent(json_encode($data,JSON_UNESCAPED_UNICODE));
- $responseResult = $alipayClient->execute($request);
- $responseApiName = str_replace(".","_",$request->getApiMethodName())."_response";
- $response = $responseResult->$responseApiName;
- Yii::$app->custom->logs('支付宝代付请求', [
- 'res' => $response,
- 'data' => $data
- ]);
- if (empty($response)) {
- throw new RuntimeException('alipay.fund.trans.uni.transfer(单笔转账接口) 响应空');
- }
- if (is_array($response)) {
- return $response;
- }
- if (!is_object($response)) {
- throw new RuntimeException('alipay.fund.trans.uni.transfer(单笔转账接口) 响应参数类型错误');
- }
- return ArrayHelper::toArray($response);
- }
- }
|