$this->mall_id]))->getAlipayConfig(); if (empty($config)) { throw new Exception('未定义配置'); } $this->config = $config; $this->setAlipayConfig(); $this->setAopClient(); } /** * 设置AlipayConfig * * @param AlipayConfig $alipay_config * @return void */ public function setAlipayConfig($alipay_config = null) { if (empty($alipay_config)) { $alipay_config = new AlipayConfig(); $alipay_config->setServerUrl(self::SERVICE_URL); $alipay_config->setAppId($this->config['app_id']); $alipay_config->setPrivateKey(trim($this->config['private_key'])); $alipay_config->setFormat(self::FORMAT); // $alipay_config->setAlipayPublicKey(trim($this->config['alipay_publicKey'])); $alipay_config->setCharset(self::CHAR); $alipay_config->setSignType(self::SIGNTYPE); $alipay_config->setAlipayPublicCertContent(trim($this->config['alipay_public_key'])); $alipay_config->setAppCertContent(trim($this->config['app_public_key'])); $alipay_config->setRootCertContent(trim($this->config['alipay_root'])); } $this->alipayConfig = $alipay_config; } /** * 设置AopClient * * @return void */ public function setAopClient() { $this->aopClient = new AopClient($this->alipayConfig); } public function setAopCertClient() { $this->aopClient = new AopCertClient($this->alipayConfig); } /** * 用户协议签约的页面接口 * * @return string */ public function agreementPageSign($external_agreement_no) { $request = new AlipayUserAgreementPageSignRequest(); $content = [ // 请按当前接入的方式进行填充,且输入值必须为文档中的参数取值范围。 // 扫码或者短信页面签约需要拼装http的请求地址访问中间页面,钱包h5页面签约可直接拼接scheme的请求地址 'access_params' => [ 'channel' => 'QRCODE', ], // 协议产品码,商户和支付宝签约时确定,不同业务场景对应不同的签约产品码。 'personal_product_code' => 'FUND_SAFT_SIGN_WITHHOLDING_P', // 签约场景 'sign_scene' => 'INDUSTRY|SATF_ACC', // 第三方主体类型 'third_party_type' => 'PARTNER', // 商家签约的产品码,固定值 'product_code' => 'FUND_SAFT_SIGN_WITHHOLDING', // 商户签约号,协议中标示用户的唯一签约号(确保在商户系统中唯一)。 格式规则:支持大写小写字母和数字,最长32位。 'external_agreement_no' => $external_agreement_no, ]; $request->setNotifyUrl( \Yii::$app->services->setting->get('system.api_url') . '/avoid-tax/notify/account?mall_id=' . $this->mall_id ); $this->setAopCertClient(); $request->setBizContent(Json::encode( $content )); return $responseResult = $this->aopClient->pageExecute($request); } /** * 签约查询 * * @param string $external_agreement_no * @return boolean|object */ public function agreementQuery($external_agreement_no) { $request = new AlipayUserAgreementQueryRequest(); $content = array_merge( [ // 个人产品码,固定值。 'personal_product_code' => 'FUND_SAFT_SIGN_WITHHOLDING_P', // 场景码,固定值。 'sign_scene' => 'INDUSTRY|SATF_ACC', // 商户产品码,固定值。 'product_code' => 'FUND_SAFT_SIGN_WITHHOLDING', // 必传 ? 'third_party_type' => 'PARTNER', ], compact('external_agreement_no') ); $this->setAopCertClient(); return $this->getResponse($request, $content); } /** * 记帐本开通 * * @param string $merchant_user_id 外部商户系统会员的唯一标识,用于开户时候的唯一性约束管控 * @param string $agreement_no 支付宝协议号 * @return boolean|object */ public function accountbookCreate($merchant_user_id, $agreement_no) { $request = new AlipayFundAccountbookCreateRequest(); $content = [ // 资金记账本的业务场景,固定值。 'scene_code' => 'SATF_FUND_BOOK', // 外部商户用户类型,固定值。 'merchant_user_type' => 'BUSINESS_ORGANIZATION', // 外部商户系统会员的唯一标识,用于开户时候的唯一性约束管控。 'merchant_user_id' => $merchant_user_id, // 支付宝协议号 'ext_info' => compact('agreement_no'), ]; $this->setAopCertClient(); return $this->getResponse($request, $content); } /** * 记帐本查询 * * @param string $account_book_id 资金记账本id * @param string $agreement_no 支付宝协议号 * @return boolean|object */ public function bookQuery($account_book_id, $agreement_no) { $request = new AlipayFundAccountbookQueryRequest(); $content = [ // 资金记账本的业务场景,固定值。 'scene_code' => 'SATF_FUND_BOOK', // 外部商户用户类型,固定值。 'account_book_id' => $account_book_id, // 支付宝协议号 'ext_info' => compact('agreement_no'), ]; $this->setAopCertClient(); return $this->getResponse($request, $content); } /** * 记账本资金专款拨入(商户给人力资源记账本转账) * * @param string $out_biz_no 商户端的唯一订单号,对于同一笔转账请求,商户需保证该订单号唯一。 * @param string $identity 记账本 id 的值 * @param string $order_title 转账业务的标题,用于在支付宝用户的账单里显示。 * @param string $agreement_no 支付宝系统中用以唯一标识用户签约记录的编号。 * @param float $trans_amount 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] * @param string $remark 业务备注 * @return boolean|object */ public function transUniTransferBook( $out_biz_no, $identity, $order_title, $agreement_no, $trans_amount, $remark = '' ) { $request = new AlipayFundTransUniTransferRequest(); $content = [ // 商户端的唯一订单号,对于同一笔转账请求,商户需保证该订单号唯一。 'out_biz_no' => $out_biz_no, // 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] 'trans_amount' => $trans_amount, // 产品码,固定值 'product_code' => 'SINGLE_TRANSFER_NO_PWD', // 资金归集,固定值。 'biz_scene' => 'DIRECT_ALLOCATION', // Participant类型,收款方信息 'payee_info' => [ // 固定值 ACCOUNT_BOOK_ID 'identity_type' => 'ACCOUNT_BOOK_ID', // 记账本 id 的值 'identity' => $identity, // 转账业务请求的扩展参数,支持传入的扩 'ext_info' => Json::encode([ // 支付宝系统中用以唯一标识用户签约记录的编号。 'agreement_no' => $agreement_no, ]), ], // 转账业务的标题,用于在支付宝用户的账单里显示。 'order_title' => $order_title, // 业务备注 'remark' => $remark, // 转账业务请求的扩展参数 'business_params' => Json::encode([ // 使用别名作为付款方显示名称,可选。收款方在支付宝账单中可见,使用详情可查看 'payer_show_name_use_alias' => true, ]), ]; $this->setAopCertClient(); return $this->getResponse($request, $content); } /** * 通过记账本转账给用户 * * @param string $out_biz_no * @param float $trans_amount * @param string $order_title * @param array $user * @param array $book * @param string $remark * @return boolean */ public function bookTransUniTransferUser( $out_biz_no, $trans_amount, $order_title, $user, $book, $remark = '' ) { $request = new AlipayFundTransUniTransferRequest(); $content = [ // 商户端的唯一订单号,对于同一笔转账请求,商户需保证该订单号唯一。 'out_biz_no' => $out_biz_no, // 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] 'trans_amount' => $trans_amount, // 产品码,固定值 'product_code' => 'SINGLE_TRANSFER_NO_PWD', // 资金归集,固定值。 'biz_scene' => 'ENTRUST_TRANSFER', // 转账业务的标题,用于在支付宝用户的账单里显示。 'order_title' => $order_title, // Participant类型,收款方信息 'payee_info' => [ // 固定值 ALIPAY_LOGON_ID 'identity_type' => 'ALIPAY_LOGON_ID', // 用户id 'identity' => $user['identity'], 'name' => $user['name'], ], // Participant类型,付款方信息 'payer_info' => [ // 记帐本ID 'identity' => $book['account_book_id'], // 固定值 ACCOUNT_BOOK_ID 'identity_type' => 'ACCOUNT_BOOK_ID', 'ext_info' => Json::encode([ 'agreement_no' => $book['agreement_no'], ]), ], // 转账业务请求的扩展参数 'business_params' => Json::encode([ // 使用别名作为付款方显示名称,可选。收款方在支付宝账单中可见,使用详情可查看 'payer_show_name_use_alias' => true, ]), // 业务备注 'remark' => $remark, ]; $this->setAopCertClient(); return $this->getResponse($request, $content); } /** * 企业支付宝单笔转账 * * @param string $out_biz_no * @param string $trans_amount * @param string $order_title * @param array $user * @param array $book * @param string $remark * @return boolean|object */ public function transUniTransferUser( $out_biz_no, $trans_amount, $order_title, $user, $product_code, $remark = '' ) { $request = new AlipayFundTransUniTransferRequest(); $content = [ // 商户端的唯一订单号,对于同一笔转账请求,商户需保证该订单号唯一。 'out_biz_no' => $out_biz_no, // 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] 'trans_amount' => $trans_amount, // 产品码,固定值 'product_code' => $product_code, // 资金归集,固定值。 'biz_scene' => 'DIRECT_TRANSFER', // 转账业务的标题,用于在支付宝用户的账单里显示。 'order_title' => $order_title, // Participant类型,收款方信息 'payee_info' => [ // 固定值 ALIPAY_LOGON_ID 'identity_type' => 'ALIPAY_LOGON_ID', // 用户id 'identity' => $user['identity'], 'name' => $user['name'], ], // 转账业务请求的扩展参数 'business_params' => Json::encode([ // 使用别名作为付款方显示名称,可选。收款方在支付宝账单中可见,使用详情可查看 'payer_show_name_use_alias' => true, ]), // 业务备注 'remark' => $remark, ]; $this->setAopCertClient(); return $this->getResponse($request, $content); } /** * 通过支付宝ID打款 * * @param string $out_biz_no * @param float $trans_amount * @param string $order_title * @param string $user_id * @param string $remark * @return array|object */ public function transUniTransferUserByUserId( string $out_biz_no, float $trans_amount, string $order_title, string $user_id, array $book, string $remark = '' ) { $request = new AlipayFundTransUniTransferRequest(); $content = [ // 商户端的唯一订单号,对于同一笔转账请求,商户需保证该订单号唯一。 'out_biz_no' => $out_biz_no, // 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] 'trans_amount' => $trans_amount, // 产品码,固定值 'product_code' => 'SINGLE_TRANSFER_NO_PWD', // 资金归集,固定值。 'biz_scene' => 'ENTRUST_TRANSFER', // 转账业务的标题,用于在支付宝用户的账单里显示。 'order_title' => $order_title, // Participant类型,收款方信息 'payee_info' => [ // 固定值 ALIPAY_USER_ID 'identity_type' => 'ALIPAY_USER_ID', // 用户id 'identity' => $user_id, ], // Participant类型,付款方信息 'payer_info' => [ // 记帐本ID 'identity' => $book['account_book_id'], // 固定值 ACCOUNT_BOOK_ID 'identity_type' => 'ACCOUNT_BOOK_ID', 'ext_info' => Json::encode([ 'agreement_no' => $book['agreement_no'], ]), ], // 转账业务请求的扩展参数 'business_params' => Json::encode([ // 使用别名作为付款方显示名称,可选。收款方在支付宝账单中可见,使用详情可查看 'payer_show_name_use_alias' => true, ]), // 业务备注 'remark' => $remark, ]; $this->setAopCertClient(); return $this->getResponse($request, $content); } /** * 记账本资金订单查询 * * @param string $out_biz_no 商户端的唯一订单号,对于同一笔转账请求,商户需保证该订单号唯一 * @return boolean|object */ public function transCommonQuery($out_biz_no) { $request = new AlipayFundTransCommonQueryRequest(); $content = [ // 产品码,和申请时候的参数一致。 'product_code' => 'SINGLE_TRANSFER_NO_PWD', // 描述特定的业务场景传入,传入下单时的场景码。 'biz_scene' => 'DIRECT_ALLOCATION', // 商户转账唯一订单号:发起转账来源方定义的转账单据 'out_biz_no' => $out_biz_no, ]; return $this->getResponse($request, $content); } /** * 实名证件信息比对验证预咨询 * * @param string $mobile * @param string $id_card * @param string $name * @return boolean|object */ public function certdocCertverifyPreconsult($mobile, $id_card, $name) { $request = new AlipayUserCertdocCertverifyPreconsultRequest(); $content = [ 'user_name' => $name, 'cert_type' => 'IDENTITY_CARD', 'cert_no' => $id_card, 'logon_id' => $mobile, ]; $this->setAopCertClient(); return $this->getResponse($request, $content); } /** * 实名证件信息比对验证咨询 * * @param string $verify_id 通过「实名证件信息比对验证预咨询」获取 * @return boolean|object */ public function certdocCertverifyConsult(string $verify_id) { $request = new AlipayUserCertdocCertverifyConsultRequest(); $content = [ 'verify_id' => $verify_id, ]; $this->setAopCertClient(); return $this->getResponse($request, $content); } /** * 换取授权访问令牌 * * @return void */ public function oauthToken($code = null) { // 授权码,用户对应用授权后得到。本参数在 grant_type 为 authorization_code 时必填;为 refresh_token 时不填。 $grant_type = empty($code) ? 'refresh_token' : 'authorization_code'; $request = new AlipaySystemOauthTokenRequest(); $request->setGrantType($grant_type); $code && $request->setCode($code); $this->setAopCertClient(); return $this->getResponseForOauthToken($request); } /** * 记账本充值 * * @param string $out_biz_no * @param float $amount * @param string $identity * @param string $agreement_no * @return void */ public function recharge( string $out_biz_no, float $amount, string $identity, string $agreement_no ) { $request = new AlipayFundTransPagePayRequest(); $content = [ 'out_biz_no' => $out_biz_no, 'trans_amount' => $amount, 'product_code' => 'FUND_ACCOUNT_BOOK', 'biz_scene' => 'SATF_DEPOSIT', 'time_expire' => date('Y-m-d H:i', strtotime('+1 hours')), 'remark' => '充值', 'order_title' => '充值', 'payee_info' => [ 'identity_type' => 'ACCOUNT_BOOK_ID', 'identity' => $identity, 'ext_info' => Json::encode([ 'agreement_no' => $agreement_no, ]), ], ]; $this->setAopCertClient(); $request->setBizContent(Json::encode( $content )); return $this->aopClient->pageExecute($request); } /** * 授权URL * * @param string $verify_id * @return string */ public function getAppAuthorizeUrl(string $verify_id) { // 若需要拼接授权 URL 时设置多个 scope,多个 scope 值间用英文逗号 , 分隔(例如:id_verify,auth_auth_user),此时获取到的授权码可在传入的场景通用。 $scope = 'id_verify'; $redirect_uri = 'https://api.qijianshigw.com'; $url = 'https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?' . 'app_id=' . $this->config['app_id'] . '&scope=' . $scope . '&redirect_uri=' . urlencode($redirect_uri) . '&cert_verify_id=' . $verify_id; return $url; } /** * 授权URL * * @return string */ public function getOAuth2Url() { $redirect_uri = 'https://testapi.qijianshigw.com/avoid-tax/notify/alipay'; $url = 'https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?' . 'app_id=' . $this->config['app_id'] . '&scope=auth_base' . '&redirect_uri=' . urlencode($redirect_uri); return $url; } /** * 记账本转账到记账本 * * @param string $out_biz_no 订单号 * @param float $trans_amount 转账金额 * @param string $order_title 转账标题 * @param string $payee_identity 收款记账本ID * @param string $payee_agreement_no 收款记账本子户开通协议号 * @param string $payer_identity 打款记账本ID * @param string $payer_agreement_no 打款记账本子户开通协议号 * @param string $remark 转账备注 * @return boolean */ public function transBookFromBook( string $out_biz_no, float $trans_amount, string $order_title, string $payee_identity, string $payee_agreement_no, string $payer_identity, string $payer_agreement_no, string $remark = '' ) { $request = new AlipayFundTransUniTransferRequest(); $content = [ // 商户端的唯一订单号,对于同一笔转账请求,商户需保证该订单号唯一。 'out_biz_no' => $out_biz_no, // 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] 'trans_amount' => $trans_amount, // 产品码,固定值 'product_code' => 'SINGLE_TRANSFER_NO_PWD', // 资金归集,固定值。 'biz_scene' => 'ENTRUST_ALLOCATION', // 转账业务的标题,用于在支付宝用户的账单里显示。 'order_title' => $order_title, // Participant类型,收款方信息 'payee_info' => [ // 固定值 ACCOUNT_BOOK_ID 'identity_type' => 'ACCOUNT_BOOK_ID', 'identity' => $payee_identity, 'ext_info' => Json::encode(['agreement_no' => $payee_agreement_no]), ], // Participant类型,付款方信息 'payer_info' => [ // 固定值 ACCOUNT_BOOK_ID 'identity_type' => 'ACCOUNT_BOOK_ID', 'identity' => $payer_identity, 'ext_info' => Json::encode(['agreement_no' => $payer_agreement_no]), ], // 业务备注 'remark' => $remark, ]; $this->setAopCertClient(); return $this->getResponse($request, $content); } /** * 查询账户余额 * * @param string $user_id * @return false|object */ public function accountQuery(string $user_id) { $request = new AlipayFundAccountQueryRequest(); $content = [ 'alipay_user_id' => $user_id, 'account_type' => 'ACCTRANS_ACCOUNT', ]; $this->setAopCertClient(); return $this->getResponse($request, $content); } /** * 获取响应值 * * @param object $request * @param array $content * @return boolean|object */ public function getResponse($request, $content = null) { !empty($content) && $request->setBizContent(Json::encode($content)); $result = $this->aopClient->execute($request); $responseNode = str_replace('.', '_', $request->getApiMethodName()) . '_response'; // 日志 Yii::$app->custom->logs('支付宝合规请求参数: ' . json_encode($content)); Yii::$app->custom->logs('支付宝合规响应参数: ' . json_encode($result->$responseNode)); $resultCode = $result->$responseNode->code; if (!empty($resultCode) && $resultCode == 10000) { return $result->$responseNode; } return $this->error($result->$responseNode->sub_msg); } /** * 获取响应 * * @param object $request * @return array */ protected function getResponseForOauthToken($request) { $result = $this->aopClient->execute($request); $responseNode = str_replace('.', '_', $request->getApiMethodName()) . '_response'; if (!empty($result->$responseNode)) { return $result->$responseNode; } return $this->error($result->error_response->sub_msg); } }