You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
825 lines
29 KiB
825 lines
29 KiB
<?php
|
|
|
|
namespace app\service\webService;
|
|
|
|
use fast\FuncException;
|
|
use think\facade\Cache;
|
|
|
|
class ChinaTaxes
|
|
{
|
|
|
|
// 用户信息
|
|
protected $puCodeUser;
|
|
// accessToken
|
|
protected $accessToken;
|
|
// 接入渠道标识(ID)
|
|
protected $channelId;
|
|
// 平台为接入渠道统一分配的密码
|
|
protected $channelSecret;
|
|
// 请求地址
|
|
protected $apiUrl;
|
|
// 密钥
|
|
protected $my = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuc3JzYmgiOiI2MjAxMDQ3NzQ0MTk4NVgiLCJpc3MiOiJTU1NIR1oiLCJkanhoIjoiMTAxMTQ0MDMwMDAwMjY0NzE2NzQiLCJzdGFydFRpbWUiOiIiLCJ1bmRUaW11IjoiMjAyMi0wNi0zMCAxODowNDo0MSIsImV4cCI6MTY1NjU4MzQ4MSwic3BqZyI6IjEifQ.Ho0H43DxSGDmydHamMABRampNaNTu3K5vJwTJzoLAMA';
|
|
// xml组合返回数据类型:1 = 返回字段标签格式、2 = 字段标签 + ns2: + 加密、3 = 字段标签 + 加密
|
|
protected $xmlType = 1;
|
|
// 申请发票信息
|
|
protected $invoiceIssuance;
|
|
// 加密XML Base标签的key
|
|
protected $xmlKey = '01';
|
|
//
|
|
protected $xmlDataType = 0;
|
|
|
|
/**
|
|
* @throws FuncException
|
|
*/
|
|
public function __construct($data = [], $invoice = [])
|
|
{
|
|
|
|
$this->puCodeUser = $data;
|
|
$this->apiUrl = env('taxes.api_url');
|
|
$this->channelId = env('taxes.channel_id'); // 接入渠道标识(ID)
|
|
$this->channelSecret = env('taxes.channel_secret'); // 平台为接入渠道统一分配的密码,只有身份验证接口需要
|
|
|
|
$this->invoiceIssuance = $invoice;
|
|
|
|
$this->getAccessToken();
|
|
}
|
|
|
|
/**
|
|
* 2.1身份验证
|
|
* @throws FuncException
|
|
*/
|
|
protected function getAccessToken()
|
|
{
|
|
$tax_key = 'tax_access_token';
|
|
$tax_access_token = Cache::get($tax_key);
|
|
if ($tax_access_token) {
|
|
$this->accessToken = $tax_access_token;
|
|
} else {
|
|
$param = [
|
|
'reqId' => $this->getReqId(), // 接入端交易请求唯一标识,长度 32 位,5 秒内不得重复,否则抛出异常:交易请求唯一标识重复。
|
|
'sid' => 'bizAccessLogin', // 调用的接口名称,固定为“bizAccessLogin”
|
|
'channelId' => $this->channelId, // 接入渠道标识(ID)
|
|
'channelSecret' => $this->channelSecret, // 平台为接入渠道统一分配的密码,只有身份验证接口需要
|
|
'timestamp' => time(), // unix 时间戳
|
|
'data' => [
|
|
'flag' => '大工业区生活垃圾处理费征收及开票需要'
|
|
] // 身份验证数据,默认为空
|
|
];
|
|
|
|
$result = $this->json_curl(json_encode($param));
|
|
if (isset($result['error'])) {
|
|
throw new FuncException($result['error']['message']);
|
|
}
|
|
|
|
if (!isset($result['result']['accessToken'])) {
|
|
throw new FuncException('返回参数有误');
|
|
}
|
|
|
|
$this->accessToken = $result['result']['accessToken'];
|
|
Cache::set($tax_key, $this->accessToken, 28680);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 发起请求参数
|
|
* @param $sid
|
|
* @param $body
|
|
* @return array
|
|
*/
|
|
protected function getParamData($sid, $body): array
|
|
{
|
|
$data = [
|
|
'reqId' => $this->getReqId(), // 接入端交易请求唯一标识
|
|
'sid' => $sid,// 调 用 的 接 口 名 称
|
|
'channelId' => $this->channelId,// 接入渠道标识
|
|
'accessToken' => $this->accessToken,// 访问令牌,由调用身份验证接口获取
|
|
'timestamp' => time(),// unix 时间戳
|
|
'data' => [
|
|
'bizXml' => !empty($body) ? $this->bizXml($body) : ''
|
|
],
|
|
];
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* 3.1保存委托代征明细数据接口
|
|
* @return array
|
|
* @throws \Exception
|
|
*/
|
|
public function savingDetailedData(): array
|
|
{
|
|
$puCodeUser = $this->puCodeUser;
|
|
$mxGrid = [];
|
|
foreach ($puCodeUser as $data) {
|
|
$userName = !empty($data['ContactName']) ? $data['ContactName']
|
|
: $data['UserName'];
|
|
$zxbz1 = strpos($data['WaterUsage'], '居民') !== false ? '0.59'
|
|
: '0.27';
|
|
$mxGrid[] = [
|
|
'bdznsrsbh' => $data['bdznsrsbh'],
|
|
// 被代征纳税人识别号 *
|
|
'bdznsrmc' => $userName,
|
|
// 被代征纳税人名称 *
|
|
'gjhdqszDm' => '156',
|
|
// 国家或地区数字代码
|
|
'sfzjlxDm' => '201',
|
|
// 身份证件类型代码
|
|
'zjhm' => !empty($data['CertificateCode'])
|
|
? $data['CertificateCode'] : '',
|
|
// 证件号码 *
|
|
'hyDm' => '6490',
|
|
// 行业代码
|
|
'zsxmDm' => '30433',
|
|
// 征收项目代码
|
|
'zspmDm' => '304331300',
|
|
// 征收品目代码
|
|
'zszmDm' => '',
|
|
// 征收子目代码
|
|
'jsyj' => $data['jsyj'],
|
|
// 计税依据,保留两位小数
|
|
'sl1' => '',
|
|
// 税率,可手工填写,不填则默认系统自动计算,保留两位小数
|
|
'ynse' => '',
|
|
// 应纳税额,可手工填写,不填则默认系统自动计算,保留两位小数
|
|
'ydzse' => '',
|
|
// 应代征税额,可手工填写,不填则默认系统自动计算,保留两位小数
|
|
'yjse' => '',
|
|
// 已缴税额,可手工填写,不填则默认系统自动计算,保留两位小数
|
|
'ydzse1' => '',
|
|
// 已代征税额,可手工填写,不填则默认系统自动计算,保留两位小数
|
|
'jmse' => '',
|
|
// 减免税额,可手工填写,不填则默认系统自动计算,保留两位小数
|
|
'phjmse' => '',
|
|
// 增值税小规模纳税人减征额
|
|
'phjzbl' => '',
|
|
// 增值税小规模纳税人减征比例
|
|
'phjmxzDm' => '',
|
|
// 增值税小规模纳税人减免性质代码
|
|
'ssjmxzDm' => '',
|
|
// 税收减免性质代码
|
|
'wszmkjbz' => 'Y',
|
|
// 完税证明开具标志为 Y 开具,N不开具
|
|
'xmmc' => $data['project_name'],
|
|
// 项目名称
|
|
'xmbm' => substr(time(), 1, 9),
|
|
// 项目编码
|
|
'username' => $userName,
|
|
// 用户名称(同一个批次,同一个用户编号下,值相同)
|
|
'nbyhbm' => $data['UserCode'],
|
|
// 用户编号
|
|
'jldwmc' => '立方米',
|
|
// 单位
|
|
'sl' => $data['WaterQty'] ?? '',
|
|
// 数量
|
|
'zxbz1' => $zxbz1,
|
|
// 标准
|
|
'skyhmc' => !empty($data['BankName']) ? $data['BankName']
|
|
: '',
|
|
// 托收银行(同一个批次,同一个用户编号下,值相同)
|
|
'yhzh' => !empty($data['BankAccountCode'])
|
|
? $data['BankAccountCode'] : '',
|
|
// 银行账号(同一个批次,同一个用户编号下,值相同)
|
|
'zsfsmc' => $data['zsfsmc'],
|
|
// 缴费方式(同一个批次,同一个用户编号下,值相同)
|
|
'tjsd' => $data['ThisLastReadingTime'],
|
|
// 收费时段(同一个批次,同一个用户编号下,值相同)
|
|
'jfyj1' => $data['jsyj'],
|
|
// 计费依据(同一个批次,同一个用户编号下,值相同)
|
|
'yhje' => '0.00',
|
|
// 优惠金额
|
|
'hjje' => $data['jsyj'],
|
|
// 合计金额
|
|
'jfrq' => $data['jfrq'],
|
|
// 缴费时间(同一个批次,同一个用户编号下,值相同)
|
|
'lxfs' => !empty($data['CellPhone']) ? $data['CellPhone']
|
|
: '',
|
|
// 联系方式(同一个批次,同一个用户编号下,值相同)
|
|
'lxdz' => !empty($data['WaterUseAddress'])
|
|
? $data['WaterUseAddress'] : '',
|
|
// 送票地址(同一个批次,同一个用户编号下,值相同)
|
|
'remark' => '无',
|
|
// 备注(同一个批次,同一个用户编号下,值相同)
|
|
'bz' => '',
|
|
// 备注信息(同一个批次,同一个用户编号下,值相同)
|
|
];
|
|
}
|
|
|
|
$body = [
|
|
'sbczlxDm' => 'insert', //申报操作类型代码,为”delete”,” insert” 或”update”
|
|
'sflsb' => 'N', //是否零申报 ,为非零申报”N”
|
|
'sbpch' => '', //批次号,详见备注
|
|
'nsqxDm' => '06', //纳税期限代码,“06”按月
|
|
'skssqq' => $this->invoiceIssuance['skssqq'], //税款所属期起,格式,年-月-日 *
|
|
'skssqz' => $this->invoiceIssuance['skssqz'], //税款所属期止,格式,年-月-日 *
|
|
'zsxmdm' => '30433', //征收项目代码:30433
|
|
'my' => $this->my, //密钥,数字签名校验和资格校验
|
|
'mxGrid' => $this->mxGrid($mxGrid)
|
|
];
|
|
|
|
$this->xmlType = 2;
|
|
|
|
$param = $this->getParamData('SSGZ_GZPT_SZQKL_WTDZDRJK', $body);
|
|
|
|
$res = $this->resultXml($param, 0);
|
|
/*if (!isset($res['sbpch'])) {
|
|
throw new FuncException('未获取到批次号');
|
|
}*/
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* 3.6实时加工委托代征明细数据接口
|
|
* @param $sbpch
|
|
* @return array
|
|
* @throws FuncException
|
|
*/
|
|
public function realTimeProcessing($sbpch): array
|
|
{
|
|
|
|
$body = [
|
|
'sbpch' => $sbpch, // 批次号,详见备注
|
|
'my' => $this->my, // 密钥,数字签名校验和资格校验
|
|
'czlx' => 'CX', // 操作类型(CX:查询;JG:加工)
|
|
];
|
|
|
|
$this->xmlKey = '06';
|
|
|
|
$param = $this->getParamData('SSGZ_GZPT_SZQKL_JGWTDZ', $body);
|
|
|
|
return $this->resultXml($param, 3);
|
|
}
|
|
|
|
/**
|
|
* 3.8开具电子缴款凭证接口
|
|
* @param $sbpch
|
|
* @param $bdznsrsbh
|
|
* @return array
|
|
* @throws FuncException
|
|
*/
|
|
public function issueElectronic($sbpch, $bdznsrsbh): array
|
|
{
|
|
|
|
$body = [
|
|
'sbpch' => $sbpch, // 批次号,详见备注
|
|
'bdzmxGrid' => [
|
|
'bdzmxlb' => []
|
|
],
|
|
'skssqq' => $this->invoiceIssuance['skssqq'], // 税款所属期起,格式,年-月-日
|
|
'skssqz' => $this->invoiceIssuance['skssqz'], // 税款所属期止,格式,年-月-日
|
|
'my' => $this->my // 密钥,数字签名校验和资格校验
|
|
];
|
|
foreach ($this->puCodeUser as $value) {
|
|
$body['bdzmxGrid']['bdzmxlb'][] = [
|
|
'bdznsrsbh' => $bdznsrsbh, // 被代征人纳税人识别号
|
|
'yhbm' => $value['UserCode'] // 用户编码
|
|
];
|
|
}
|
|
|
|
$param = $this->getParamData('SSGZ_GZPT_PZ_SQKJDZJKPZ', $body);
|
|
|
|
return $this->resultXml($param);
|
|
}
|
|
|
|
/**
|
|
* 3.9查询电子缴款凭证上链信息
|
|
* @param $assetID
|
|
* @return false[]|string[]
|
|
* @throws FuncException
|
|
*/
|
|
public function queryPaymentVoucher($assetID): array
|
|
{
|
|
|
|
$body = [
|
|
'assetID' => $assetID
|
|
];
|
|
|
|
$param = $this->getParamData('SSGZ_GZPT_PZ_QUERYDZJKPZSLXX', $body);
|
|
|
|
$result = $this->resultXml($param);
|
|
|
|
return [
|
|
'meta' => $result['pzkjxxVO']['meta'],
|
|
'data' => $result['pzkjxxVO']['data']
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 3.3 查询上传异常数据接口(未完成)
|
|
* @param $sbpch
|
|
* @return array
|
|
* @throws FuncException
|
|
*/
|
|
public function queryUploadErrorData($sbpch): array
|
|
{
|
|
$body = [
|
|
'sbpch' => $sbpch, // 批次号,详见备注
|
|
'my' => $this->my // 密钥,数字签名校验和资格校验
|
|
];
|
|
|
|
$param = $this->getParamData('SSGZ_GZPT_SZQKL_DW_DZSCMXYC_QUERY', $body);
|
|
|
|
return $this->resultXml($param);
|
|
}
|
|
|
|
/**
|
|
* 3.7 查询待开具电子缴款凭证数据接口(未完成)
|
|
* @param $bdznsrsbh
|
|
* @return array
|
|
* @throws FuncException
|
|
*/
|
|
public function queryIssuedPaymentVoucher($bdznsrsbh): array
|
|
{
|
|
$body = [
|
|
'bdzmxList' => [
|
|
'bdzmxVO' => ['bdznsrsbh' => $bdznsrsbh] // 被代征人纳税人识别号
|
|
],
|
|
'skssqq' => $this->invoiceIssuance['skssqq'], // 税款所属期起,格式,年-月-日
|
|
'skssqz' => $this->invoiceIssuance['skssqz'], // 税款所属期止,格式,年-月-日
|
|
'my' => $this->my // 密钥,数字签名校验和资格校验
|
|
];
|
|
|
|
$param = $this->getParamData('SSGZ_GZPT_PZ_QUERYDKDZJKPZ', $body);
|
|
|
|
return $this->resultXml($param);
|
|
}
|
|
|
|
/**
|
|
* 3.10身份校验接口 ---
|
|
* @param $nsrsbh // 纳税人识别号
|
|
* @return array
|
|
* @throws FuncException
|
|
*/
|
|
public function identityCheck($nsrsbh): array
|
|
{
|
|
$body = [
|
|
'sfxxList' => [
|
|
'nsrlx' => '1' // 2 非自然人、1 自然人
|
|
],
|
|
'yhbh' => $this->puCodeUser[0]['UserCode'], // 水司的用户编号
|
|
'nsrsbh' => $nsrsbh, // 传输类型为非自然人不可以为空
|
|
'nsrmc' => $this->puCodeUser[0]['ContactName'], // 不可为空
|
|
'zjhm' => $this->puCodeUser[0]['CertificateCode'], // 传输类型为自然人,不可以为空
|
|
'zjlx' => '201', // 传输类型为自然人,不可以为空,添加证件类型代码 999
|
|
'gj' => '156', // 国籍
|
|
];
|
|
|
|
$this->xmlType = 2;
|
|
$this->xmlKey = '07';
|
|
|
|
$param = $this->getParamData('SSGZ_GZPT_SZQKL_SFJYJK', $body);
|
|
|
|
return $this->resultXml($param, 0);
|
|
}
|
|
|
|
/**
|
|
* 3.14代征明细数据虚拟户更正接口
|
|
* @param $nsrsbh // 纳税人识别号
|
|
* @param $sbpch // 批次号
|
|
* @return array
|
|
* @throws FuncException
|
|
*/
|
|
public function collectionDetails($nsrsbh, $sbpch): array
|
|
{
|
|
$body = [
|
|
'gzxxList' => [
|
|
'gzxxVO' => [
|
|
'nsrlx' => 1, // 2 非自然人、1 自然人
|
|
'yhbh' => $this->puCodeUser[0]['UserCode'], // 水司的用户编号
|
|
'nsrsbh' => $nsrsbh, // 传输类型为单位不可以为空
|
|
'nsrmc' => $this->puCodeUser[0]['ContactName'], // 不可为空 ?
|
|
'zjhm' => $this->puCodeUser[0]['CertificateCode'], // 传输类型为自然人,不可以为空
|
|
'zjlx' => '201', // 传输类型为自然人,不可以为空,添加证件类型代码 999
|
|
'gj' => '156', // 国籍
|
|
'username' => $this->puCodeUser[0]['UserName'], // 用户名称
|
|
'skyhmc' => $this->puCodeUser[0]['BankName'], // 托收银行
|
|
'yhzh' => $this->puCodeUser[0]['BankAccountCode'], // 银行账号
|
|
'lxdz' => $this->puCodeUser[0]['MaillingAddress'], // 用户地址
|
|
'lxfs' => $this->puCodeUser[0]['Telephone'], // 联系方式
|
|
'sbpch' => $sbpch, // 申报批次号
|
|
],
|
|
],
|
|
'my' => $this->my // 密钥,数字签名校验和资格校验
|
|
];
|
|
|
|
$this->xmlType = 3;
|
|
$this->xmlKey = '10';
|
|
|
|
$param = $this->getParamData('SSGZ_GZPT_SZQKL_SB_XNHGZ', $body);
|
|
|
|
return $this->resultXml($param);
|
|
}
|
|
|
|
/**
|
|
* 3.2作废委托代征明细数据接口(未完成)
|
|
* @throws FuncException
|
|
*/
|
|
public function invalidEntrustCollection($sbpch): array
|
|
{
|
|
$body = [
|
|
'sbpch' => $sbpch, // 批次号,详见备注
|
|
'my' => $this->my // 密钥,数字签名校验和资格校验
|
|
];
|
|
|
|
$param = $this->getParamData('SSGZ_GZPT_SZQKL_DELETEWTDZ', $body);
|
|
|
|
return $this->resultXml($param);
|
|
}
|
|
|
|
/**
|
|
* 3.12代征明细数据汇总确认查询接口
|
|
* @throws FuncException
|
|
*/
|
|
public function daiZhengSummaryQuery($bdznsrsbh): array
|
|
{
|
|
|
|
$body = [
|
|
'my' => $this->my, // 密钥,数字签名校验和资格校验
|
|
'bdznsrsbh' => $bdznsrsbh, // 被代征人纳税人识别号
|
|
'skssqq' => $this->invoiceIssuance['skssqq'], // 税款所属期起,格式,年-月-日
|
|
'skssqz' => $this->invoiceIssuance['skssqz'], // 税款所属期止,格式,年-月-日
|
|
];
|
|
|
|
$this->xmlDataType = 1;
|
|
|
|
$param = $this->getParamData('SSGZ_GZPT_SZQKL_SB_CXDZMXSJHZ', $body);
|
|
|
|
return $this->resultXml($param);
|
|
}
|
|
|
|
/**
|
|
* 3.13代征明细数据汇总确认结报接口
|
|
* @param $zje // 总金额
|
|
* @return array
|
|
* @throws FuncException
|
|
*/
|
|
public function daiZhengSummaryReport($zje): array
|
|
{
|
|
$body = [
|
|
'my' => $this->my, // 密钥,数字签名校验和资格校验
|
|
'zje' => $zje, // 总金额
|
|
'skssqq' => $this->invoiceIssuance['skssqq'], // 税款所属期起,格式,年-月-日
|
|
'skssqz' => $this->invoiceIssuance['skssqz'], // 税款所属期止,格式,年-月-日
|
|
];
|
|
|
|
$param = $this->getParamData('SSGZ_GZPT_SZQKL_SB_BCWTDZHZJK', $body);
|
|
|
|
return $this->resultXml($param);
|
|
}
|
|
|
|
/**
|
|
* 3.11税收完税证明换开申请接口 !!!
|
|
* @param $bdznsrsbh
|
|
* @return array
|
|
* @throws FuncException
|
|
*/
|
|
public function taxationReplaceApply($bdznsrsbh): array
|
|
{
|
|
$body = [
|
|
'my' => $this->my, // 密钥,数字签名校验和资格校验
|
|
'bdznsrsbh' => $bdznsrsbh, // 被代征人纳税人识别号
|
|
'skssqq' => $this->invoiceIssuance['skssqq'], // 税款所属期起,格式,年-月-日
|
|
'skssqz' => $this->invoiceIssuance['skssqz'], // 税款所属期止,格式,年-月-日
|
|
];
|
|
|
|
$param = $this->getParamData('SSGZ_GZPT_SZQKL_ZM_SAVEPLSQKJSSWSZMJK', $body);
|
|
|
|
return $this->resultXml($param);
|
|
}
|
|
|
|
/**
|
|
* 3.15查询作废的电子缴款凭证接口 ---
|
|
* @throws FuncException
|
|
*/
|
|
public function queryInvalidPaymentVoucher($assetID): array
|
|
{
|
|
$body = [
|
|
'my' => $this->my, // 密钥,数字签名校验和资格校验
|
|
'zfqq' => $this->invoiceIssuance['skssqq'], // 作废期起,格式,年-月-日,查询作废时间内作废的票证,返回相应的 assetid
|
|
'zfqz' => $this->invoiceIssuance['skssqz'], // 作废期止,格式,年-月-日,查询作废时间内作废的票证,返回相应的 assetid
|
|
'assetid' => $assetID, // 电子缴款凭证开具返回的 assetid,填写这个参数只查验单个票证是否作废
|
|
];
|
|
|
|
$param = $this->getParamData('SSGZ_GZPT_SZQKL_PZ_QUERYDZJKPZZFQK', $body);
|
|
|
|
return $this->resultXml($param);
|
|
}
|
|
|
|
/**
|
|
* 3.4申请开具接口 !!!
|
|
* @param $nsrsbh
|
|
* @param $sbpch
|
|
* @return array
|
|
* @throws FuncException
|
|
*/
|
|
public function applyIssued($nsrsbh, $sbpch): array
|
|
{
|
|
$body = [
|
|
'bhzrnsrsbhs' => [
|
|
'nsrsbh' => $nsrsbh // 纳税人识别号
|
|
],
|
|
'skssqq' => $this->invoiceIssuance['skssqq'], // 税款所属期起,格式,年-月-日
|
|
'skssqz' => $this->invoiceIssuance['skssqz'], // 税款所属期止,格式,年-月-日
|
|
'mm' => $this->my, // 密钥,数字签名校验和资格校验
|
|
'pch' => $sbpch, // 文件名,英文或数字,长度在 20 位,且唯一
|
|
];
|
|
|
|
$param = $this->getParamData('SSGZ_GZPT_SZQKL_ZM_SAVEPLSQKJSSWSZMFORWXT', $body);
|
|
|
|
return $this->resultXml($param);
|
|
}
|
|
|
|
/**
|
|
* 3.5下载完税证明 !!!
|
|
*/
|
|
public function downTaxPaymentProve($djxh, $bq): string
|
|
{
|
|
|
|
$param = [
|
|
'ctrl=PlkjwszmCtrl_jkxzWszmxx', // 必填,功能模块名称,固定值为“PlkjwszmCtrl_jkxzWszmxx“
|
|
'token=' . $this->accessToken, // 必填,令牌,即通过前台资格校验模块生成的密钥
|
|
'djxh=' . $djxh, // 必填,代征单位登记序号
|
|
'bq=' . $bq // 必填,标签,即申请开具接口的的 pch 字段,是唯一的一个文件名称
|
|
];
|
|
|
|
$paramStr = implode('&', $param);
|
|
|
|
return env('taxes_down_url') . '?' . $paramStr; // 必填,请求路径
|
|
}
|
|
|
|
/**
|
|
* 处理 body 报文
|
|
* @param $body
|
|
* @return string
|
|
*/
|
|
protected function bizXml($body): string
|
|
{
|
|
$xmlKey = $this->xmlKey;
|
|
$start = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<SZQKLDZSPSB00'.$xmlKey.'ZipBase64RequestBw
|
|
xmlns:ns2="http://www.chinatax.gov.cn/dataspec/">';
|
|
$start1 = '<SZQKLDZSPSB00'.$xmlKey.'ZipBase64RequestBw>';
|
|
$end = '</SZQKLDZSPSB00'.$xmlKey.'ZipBase64RequestBw>';
|
|
|
|
$xml = $this->bizXmlStr($body, $this->xmlType == 2 ? $this->xmlType : 1);
|
|
|
|
// 需要ns2 前后组合 加密返回
|
|
if ($this->xmlType == 2) {
|
|
return $start1 . $this->enCompressXml($start . $xml . $end) . $end;
|
|
}
|
|
|
|
if ($this->xmlType == 3) {
|
|
$startXml = '<?xml version="1.0" encoding="UTF-8"?>
|
|
<!--用XMLSpy v2013 sp1产生的 XML文件(http://www.altova.com)-->
|
|
<taxML xsi:type="SZQKLDZSPSB0010ZipBase64RequestBw" bbh="String" xmlbh="String" xmlmc="String" xsi:schemaLocation="http://www.chinatax.gov.cn/dataspec/ TaxMLBw_SZQKLDZSP_0010_ZipBase64RequestBw.xsd" xmlns="http://www.chinatax.gov.cn/dataspec/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
|
|
$endXml = '</taxML>';
|
|
$enCompressXml = $this->enCompressXml($startXml . $xml . $endXml);
|
|
return $start1 . $enCompressXml . $end;
|
|
}
|
|
|
|
// 直接返回
|
|
return $xml;
|
|
}
|
|
|
|
/**
|
|
* 循环处理bizXml数据
|
|
* @param $body
|
|
* @param int $type
|
|
* @param string $lastKey
|
|
* @return string
|
|
*/
|
|
protected function bizXmlStr($body, int $type = 1, string $lastKey = ''): string
|
|
{
|
|
$xml = '';
|
|
foreach ($body as $key => $value) {
|
|
if (is_numeric($key) && !empty($lastKey)) {
|
|
$xml .= $this->bizXmlStr($value, $type, $lastKey);
|
|
continue;
|
|
}
|
|
if (is_array($value)) {
|
|
if ($type == 2) {
|
|
$xml .= "<ns2:{$key}>" . $this->bizXmlStr($value, $type, $key) . "</ns2:{$key}>";
|
|
} else {
|
|
$xml .= "<$key>" . $this->bizXmlStr($value, $type, $key) . "</$key>";
|
|
}
|
|
} else {
|
|
if ($type == 2) {
|
|
$xml .= "<ns2:{$key}>" . $value . "</ns2:{$key}>";
|
|
} else {
|
|
$xml .= "<$key>$value</$key>";
|
|
}
|
|
}
|
|
}
|
|
return $xml;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param $mxGrid
|
|
* @return string
|
|
*/
|
|
protected function mxGrid($mxGrid): string
|
|
{
|
|
$xmlStr = '';
|
|
foreach ($mxGrid as $data) {
|
|
$xmlStr .= '<ns2:sbMxsjVOList>';
|
|
foreach ($data as $key => $value) {
|
|
|
|
$xmlStr .= "<ns2:{$key}>" . $value . "</ns2:{$key}>";
|
|
}
|
|
$xmlStr .= '</ns2:sbMxsjVOList>';
|
|
}
|
|
|
|
return $xmlStr;
|
|
}
|
|
|
|
/**
|
|
* 发送请求JSON
|
|
* @param $json
|
|
* @return bool|string
|
|
* @throws FuncException
|
|
*/
|
|
protected function json_curl($json)
|
|
{
|
|
// 初始化cURL会话
|
|
$ch = curl_init();
|
|
|
|
// 设置cURL选项
|
|
curl_setopt($ch, CURLOPT_URL, $this->apiUrl); // 目标URL
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回结果而不是输出
|
|
curl_setopt($ch, CURLOPT_POST, true); // 发送POST请求
|
|
|
|
// 设置POST字段
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); // 设置HTTP头
|
|
|
|
// 跳过证书验证(不推荐在生产环境使用)
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
|
|
// 跳过主机名验证
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
|
|
|
// 执行cURL会话
|
|
$response = curl_exec($ch);
|
|
|
|
// 检查是否有错误发生
|
|
if (curl_errno($ch)) {
|
|
throw new FuncException('请求失败');
|
|
}
|
|
|
|
// 关闭cURL会话
|
|
curl_close($ch);
|
|
|
|
return json_decode($response, true);
|
|
}
|
|
|
|
/**
|
|
* 获取接入端交易请求唯一标识
|
|
* @return string
|
|
*/
|
|
protected function getReqId(): string
|
|
{
|
|
return md5(time() . rand(0, 9));
|
|
}
|
|
|
|
/**
|
|
* 装换xml数据为数组
|
|
* @param $xmlData
|
|
* @return array|mixed
|
|
*/
|
|
protected function xmlDom($xmlData)
|
|
{
|
|
$dom = new \DOMDocument();
|
|
$dom->loadXML($xmlData);
|
|
return $this->xmlToArray($dom->documentElement);
|
|
}
|
|
|
|
/**
|
|
* 加密
|
|
* @param $str
|
|
* @return array|string|string[]
|
|
*/
|
|
protected function enCompressXml($str)
|
|
{
|
|
$gzencode = gzencode($str);
|
|
$baseStr = base64_encode($gzencode);
|
|
return str_replace(array("\n", "\r"), array('{n}', '{r}'), $baseStr);
|
|
}
|
|
|
|
/**
|
|
* 解密
|
|
* @param $str
|
|
* @return false|string
|
|
*/
|
|
protected function deCompressXml($str)
|
|
{
|
|
$repStr = str_replace(array('{n}', '{r}'), array("\n", "\r"), $str);
|
|
$baseStr = base64_decode($repStr);
|
|
return gzdecode($baseStr);
|
|
}
|
|
|
|
/**
|
|
* 转换xml为数组
|
|
* @param $node
|
|
* @return array|mixed
|
|
*/
|
|
protected function xmlToArray($node)
|
|
{
|
|
$output = [];
|
|
|
|
if ($node->hasChildNodes()) {
|
|
foreach ($node->childNodes as $child) {
|
|
if ($child->nodeType === XML_ELEMENT_NODE) {
|
|
$data = $this->xmlToArray($child);
|
|
if ($this->xmlDataType == 1 && is_array($data)) {
|
|
$output[$child->nodeName][] = $data;
|
|
} else {
|
|
$output[$child->nodeName] = $data;
|
|
}
|
|
} elseif ($child->nodeType === XML_TEXT_NODE) {
|
|
$output = $child->nodeValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
|
|
/**
|
|
* 处理返回的XML数据
|
|
* @param $param
|
|
* @param int $type
|
|
* @return array
|
|
* @throws FuncException
|
|
*/
|
|
protected function resultXml($param, int $type = 1): array
|
|
{
|
|
$key = "SZQKLDZSPSB00{$this->xmlKey}ZipBase64ResponsBw";
|
|
$result = $this->json_curl(json_encode($param));
|
|
|
|
// 恢复修改
|
|
$this->xmlKey = '01';
|
|
$this->xmlType = 1;
|
|
|
|
if (!isset($result['result'])) {
|
|
if (isset($result['error']['message'])) {
|
|
throw new FuncException($result['error']['message']);
|
|
}
|
|
throw new FuncException('请求失败');
|
|
}
|
|
$data = $this->xmlDom($result['result']);
|
|
|
|
if (isset($data['code']) && $data['code'] != 200) {
|
|
if ($type == 1 && $data['code'] == 302) return $data;
|
|
throw new FuncException($data['message']);
|
|
} else if ($type == 1) {
|
|
if (isset($data[$key])) {
|
|
$data['zipBaseData'] = $this->deCompressXml($data[$key]);
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
$deData = $this->deCompressXml($data[$key]);
|
|
|
|
if ($deData) {
|
|
$xmlData = $this->xmlDom($deData);
|
|
|
|
if (isset($xmlData['ns2:code']) && $xmlData['ns2:code'] != 200) {
|
|
if ($xmlData['ns2:message'] != '已结报的属期,不允许导入') {
|
|
throw new FuncException($xmlData['ns2:message']);
|
|
}
|
|
}
|
|
|
|
$returnData = $this->delNs2Filed($xmlData);
|
|
|
|
if ($type == 3) {
|
|
$data['data'] = $returnData;
|
|
$returnData = $data;
|
|
}
|
|
|
|
return $returnData;
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* 处理xml数据
|
|
* @param $returnData
|
|
* @return mixed
|
|
*/
|
|
protected function delNs2Filed($returnData)
|
|
{
|
|
foreach ($returnData as $oldKey => $value) {
|
|
$newKey = str_replace('ns2:', '', $oldKey);
|
|
if (is_array($value)) {
|
|
$value = $this->delNs2Filed($value);
|
|
}
|
|
$returnData[$newKey] = $value;
|
|
if ($newKey != $oldKey) {
|
|
unset($returnData[$oldKey]);
|
|
}
|
|
}
|
|
return $returnData;
|
|
}
|
|
}
|
|
|