mirror of
https://gitee.com/ShopeX/OMS
synced 2026-04-01 05:26:43 +08:00
426 lines
18 KiB
PHP
426 lines
18 KiB
PHP
<?php
|
||
/**
|
||
* Copyright © ShopeX (http://www.shopex.cn). All rights reserved.
|
||
* See LICENSE file for license details.
|
||
*/
|
||
|
||
/**
|
||
* 电子发票接口事件类
|
||
*
|
||
* @author xiayuanjun<xiayuanjun@shopex.cn>
|
||
* @version 0.1
|
||
*/
|
||
class invoice_event_trigger_einvoice extends invoice_event_response
|
||
{
|
||
/**
|
||
* 电子发票开票(蓝票)发起方法
|
||
*
|
||
* @param string $shop_id 来源店铺ID
|
||
* @param array $data 开电子发票(开蓝票)通知数据信息
|
||
* @param string $error_msg
|
||
* @return array
|
||
*/
|
||
public function create($shop_id, &$data, &$error_msg=null)
|
||
{
|
||
$data['ship_tel'] = ($index = strpos($data['ship_tel'], '>>')) ? substr($data['ship_tel'], 0, $index) : $data['ship_tel'];
|
||
//开票配置信息
|
||
$rs = kernel::single('invoice_func')->get_order_setting($shop_id, $data['mode']);
|
||
$rs_setting = $rs[0];
|
||
|
||
#电子发票,没有开票信息设置的,不创建
|
||
if ($data['mode'] == 1 && empty($rs_setting)) {
|
||
$error_msg = '当前店铺没有配置电子发票开票信息';
|
||
return false;
|
||
}
|
||
|
||
$updateData['payee_name'] = $data['payee_name'] = $rs_setting["payee_name"] ? $rs_setting["payee_name"] : '';
|
||
$updateData['tax_no'] = $data['tax_no'] = $rs_setting["tax_no"] ? $rs_setting["tax_no"] : '';
|
||
$updateData['address'] = $data['address'] = $rs_setting["address"] ? $rs_setting["address"] : '';
|
||
$updateData['telephone'] = $data['telephone'] = $rs_setting["telphone"] ? $rs_setting["telphone"] : '';
|
||
$updateData['payee_operator'] = $data['payee_operator'] = $rs_setting["payee_operator"] ? $rs_setting["payee_operator"] : '';
|
||
$updateData['bank'] = $data['bank'] = $rs_setting["bank"] ? $rs_setting["bank"] : '';
|
||
$updateData['bank_no'] = $data['bank_no'] = $rs_setting["bank_no"] ? $rs_setting["bank_no"] : '';
|
||
$updateData['payee_checker'] = $data['payee_checker'] = $rs_setting['payee_checker'] ? $rs_setting['payee_checker'] : '';
|
||
$updateData['payee_receiver'] = $data['payee_receiver'] = $rs_setting['payee_receiver'] ? $rs_setting['payee_receiver'] : '';
|
||
$updateData['tax_rate'] = $data['tax_rate'] = $rs_setting['tax_rate'] ? $rs_setting['tax_rate'] : '';
|
||
//组织发票数据
|
||
$sdf = kernel::single('invoice_event_trigger_data_router')->set_shop_id($shop_id)->getEinvoiceRequestParams($data, 'blue');
|
||
if (!$sdf || $sdf['rsp']=='fail'){
|
||
$error_msg = $sdf['error_msg'];
|
||
return false;
|
||
}
|
||
// 保存开票内容
|
||
if ($data['serial_no']) {
|
||
$invEleItemMdl = app::get('invoice')->model('order_electronic_items');
|
||
$invEleItemMdl->update(['content' => json_encode($sdf)],['serial_no' => $data['serial_no']]);
|
||
}
|
||
//更新配置信息
|
||
app::get('invoice')->model('order')->update($updateData,['id'=>$data['id']]);
|
||
//判断是否加密
|
||
$shop = app::get('ome')->model('shop')->db_dump($data['shop_id'],'node_id');
|
||
|
||
$encryptKey = array (
|
||
'ship_tel' => $data['ship_tel'],
|
||
'ship_bank_no' => $data['ship_bank_no'],
|
||
'ship_company_tel' => $data['ship_company_tel'],
|
||
);
|
||
$result = kernel::single('ome_security_router', $data['shop_type'])->is_encrypt($encryptKey,'invoice');
|
||
if($result){
|
||
$sdf['s_node_id'] = $shop['node_id'];
|
||
$sdf['s_node_type'] = $data['shop_type'];
|
||
$sdf['order_bns'] = $data['order_bn'];
|
||
$sdf['ship_tel'] = $data['ship_tel'];
|
||
$sdf['ship_bank'] = $data['ship_bank'];
|
||
$sdf['ship_bank_no'] = $data['ship_bank_no'];
|
||
$sdf['ship_company_tel'] = $data['ship_company_tel'];
|
||
|
||
$sdf['is_encrypt'] = true;
|
||
}
|
||
|
||
//request
|
||
if ($sdf['order_bn'] && $sdf['invoice_type'] == 'merge') {
|
||
$orderBns = explode(',',$sdf['order_bn']);
|
||
if ($orderBns > 2) {
|
||
list($firstOrder,$secondOrder) = explode(',',$sdf['order_bn']);
|
||
$sdf['order_bn'] = $firstOrder.','.$secondOrder;
|
||
}
|
||
}
|
||
$invoiceMdl = app::get('invoice')->model('order');
|
||
//开票发起前 标记开电子发票同步状态为 开蓝票中
|
||
$filter_arr = array("id" => $sdf['order']["id"]);
|
||
$update_sync_arr = array (
|
||
"sync" => "1",
|
||
"channel_id" => $sdf['order']['channel_id'],
|
||
);//提前标记开蓝票中的状态
|
||
if (isset($data['channel_golden_tax_version'])) {
|
||
$update_sync_arr['golden_tax_version'] = $data['channel_golden_tax_version'];
|
||
}
|
||
|
||
$invoiceMdl->update($update_sync_arr, $filter_arr);
|
||
|
||
$result = kernel::single('erpapi_router_request')->set('invoice', $shop_id)->invoice_create($sdf);
|
||
|
||
// 失败处理
|
||
if($result["rsp"] == "fail"){
|
||
$update["sync"] = "2"; //开蓝失败
|
||
$update["is_status"] = "0"; //保持为:未开票状态
|
||
$update["sync_msg"] = $result["err_msg"];
|
||
|
||
//更新发票记录主表
|
||
$filter = ["id" => $data['id']];
|
||
$invoiceMdl->update($update, $filter);
|
||
kernel::single('monitor_event_notify')->addNotify('invoice_result_error', [
|
||
'invoice_type' => 'B2C发票开蓝失败',
|
||
'order_bn' => $data['order_bn'],
|
||
'errmsg' => $result['err_msg'],
|
||
]);
|
||
}else{
|
||
//百望开票响应没有开票状态,直接更新为开票中然后去走获取开票结果脚本更新
|
||
if ($data['channel_type'] == 'baiwang') {
|
||
app::get('invoice')->model('order_electronic_items')->update(['invoice_status' => '10'],['serial_no' => $data['serial_no']]);
|
||
}
|
||
|
||
if (is_string($result['data'])) {
|
||
$result['data'] = @json_decode($result['data'], true);
|
||
}
|
||
$result['data']['msg_id'] = $result['msg_id'];
|
||
// 模拟接口回传, 触发更新
|
||
kernel::single('erpapi_router_response')->set_node_id($data['channel_node_id'])->set_api_name('invoice.order.status_update')->dispatch($result['data']);
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 电子发票开票作废(红票)发起方法
|
||
*
|
||
* @param string $shop_id 来源店铺ID
|
||
* @param array $data 作废电子发票(冲红)通知数据信息
|
||
* @return array
|
||
*/
|
||
public function cancel($shop_id, &$data)
|
||
{
|
||
$data['ship_tel'] = ($index = strpos($data['ship_tel'], '>>')) ? substr($data['ship_tel'], 0, $index) : $data['ship_tel'];
|
||
|
||
$dataLib = kernel::single('invoice_event_trigger_data_router')->set_shop_id($shop_id);
|
||
|
||
// 确认当前订单红冲是否需确认
|
||
$needConfirm = $dataLib->checkCancelConfirm($data);
|
||
|
||
// 如需确认,则先发起红字申请单,待确认后红冲
|
||
if($needConfirm){
|
||
$result = kernel::single('invoice_event_trigger_redapply')->create($shop_id, $data);
|
||
|
||
// 格式化错误信息
|
||
$result['msg'] = '红字确认单申请失败:'.$result['msg'].'('.$result['msg_id'].')';
|
||
if ($result['rsp'] == 'succ'){
|
||
$result['msg'] = '红字确认单申请中('.$result['msg_id'].')';
|
||
}else{
|
||
//失败预警
|
||
kernel::single('monitor_event_notify')->addNotify('invoice_result_error', [
|
||
'invoice_type' => 'B2C红字确认单申请失败',
|
||
'order_bn' => $data['order_bn'],
|
||
'errmsg' => $result['err_msg'],
|
||
]);
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
$sdf = $dataLib->getEinvoiceRequestParams($data, 'red');
|
||
|
||
if (!$sdf) {
|
||
return $this->send_error('冲红参数错误');
|
||
}
|
||
// 判断是否加密
|
||
$shop = app::get('ome')->model('shop')->db_dump($data['shop_id'],'node_id');
|
||
if (kernel::single('ome_security_router',$data['shop_type'])->is_encrypt(array ('ship_tel' => $data['ship_tel']),'invoice')) {
|
||
$sdf['s_node_type'] = $data['shop_type'];
|
||
$sdf['s_node_id'] = $shop['node_id'];
|
||
$sdf['order_bns'] = $data['order_bn'];
|
||
$sdf['is_encrypt'] = true;
|
||
}
|
||
|
||
if ($sdf['order_bn'] && $sdf['invoice_type'] == 'merge') {
|
||
$orderBns = explode(',',$sdf['order_bn']);
|
||
if ($orderBns > 2) {
|
||
list($firstOrder,$secondOrder) = explode(',',$sdf['order_bn']);
|
||
$sdf['order_bn'] = $firstOrder.','.$secondOrder;
|
||
}
|
||
}
|
||
// 开票发起前 标记开电子发票同步状态为 开红票中
|
||
$invoiceMdl = app::get('invoice')->model('order');
|
||
$filter_arr = array("id" => $data['id']);
|
||
$update_sync_arr = array("sync" => "4");//标记开红票中的状态
|
||
$invoiceMdl->update($update_sync_arr, $filter_arr);
|
||
//百望取消走红字确认单
|
||
if ($data['channel_type'] != 'baiwang' || $data['channel_golden_tax_version'] != 1) {
|
||
$result = kernel::single('erpapi_router_request')->set('invoice',$shop_id)->invoice_cancel($sdf);
|
||
}else{
|
||
$sdf = $dataLib->getCancelApplyRequestParams($data);
|
||
|
||
if (!$sdf) {
|
||
return $this->send_error('冲红红字确认单参数错误');
|
||
}
|
||
|
||
$result = kernel::single('erpapi_router_request')->set('invoice', $shop_id)->redapply_create($sdf);
|
||
$createRes = is_string($result['data']) ? json_decode($result['data'], true) : $result['data'];
|
||
$responseParams = [
|
||
'invoice' => $data,
|
||
'data' => $createRes,
|
||
];
|
||
|
||
kernel::single('erpapi_router_response')->set_node_id($data['channel_node_id'])->set_api_name('invoice.redapply.status_update')->dispatch($responseParams);
|
||
}
|
||
|
||
// 格式化错误信息
|
||
$result['msg'] = '冲红失败:'.$result['msg'].'('.$result['msg_id'].')';
|
||
if ($result['rsp'] == 'succ'){
|
||
$result['msg'] = '冲红中('.$result['msg_id'].')';
|
||
}
|
||
|
||
// 失败处理
|
||
if ($result["rsp"] == "fail") {
|
||
|
||
$update = [
|
||
'sync' => '5',
|
||
'is_status' => '1',
|
||
'sync_msg' => $result['err_msg'],
|
||
];
|
||
|
||
$filter = ['id' => $data['id'], 'sync' => ['3', '4', '5']];
|
||
$invoiceMdl->update($update, $filter);
|
||
|
||
kernel::single('monitor_event_notify')->addNotify('invoice_result_error', [
|
||
'invoice_type' => 'B2C发票冲红失败',
|
||
'order_bn' => $data['order_bn'],
|
||
'errmsg' => $result['err_msg'],
|
||
]);
|
||
} else {
|
||
if (is_string($result['data'])) {
|
||
$result['data'] = @json_decode($result['data'], true);
|
||
}
|
||
$result['data']['msg_id'] = $result['msg_id'];
|
||
// 模拟接口回传, 触发更新
|
||
if ($data['channel_type'] != 'baiwang' || $data['channel_golden_tax_version'] != 1) {
|
||
kernel::single('erpapi_router_response')->set_node_id($data['channel_node_id'])->set_api_name('invoice.order.status_update')->dispatch($result['data']);
|
||
}
|
||
}
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 电子发票开票(蓝票或者红票)后获取发票开票结果查询
|
||
* @param string $shop_id 来源店铺ID
|
||
* @param array $data 开电子发票(开蓝票或者红票)后获取发票开票结果查询 通知数据信息
|
||
* @return array
|
||
*/
|
||
public function getEinvoiceCreateResult($item_id, $sendsms=true)
|
||
{
|
||
$invEleItemMdl = app::get('invoice')->model('order_electronic_items');
|
||
$invOrderMdl = app::get('invoice')->model('order');
|
||
$shopMdl = app::get('ome')->model('shop');
|
||
$opObj = app::get('ome')->model('operation_log');
|
||
|
||
$item = $invEleItemMdl->db_dump($item_id);
|
||
if ($item['invoice_status'] == '0') {
|
||
return array('true');
|
||
}
|
||
if (!$item['serial_no']) {
|
||
return array('fail','开票交易流水号不存在');
|
||
}
|
||
|
||
$invoice = $invOrderMdl->db_dump($item['id']);
|
||
if ( $invoice['mode'] != '1' || !in_array($invoice['sync'],array('1','4','7','9'))) {
|
||
return array('fail','电子发票未同步中,无需同步');
|
||
}
|
||
|
||
$shop = $shopMdl->db_dump($invoice['shop_id']);
|
||
|
||
$data = array(
|
||
'serial_no' => $item['serial_no'],
|
||
'order_bn' => $invoice['order_bn'],
|
||
'payee_register_no' => $invoice['tax_no'],
|
||
'node_type' => $shop['node_type'],
|
||
'node_id' => $shop['node_id'],
|
||
'shop_id' => $shop['shop_id'],
|
||
'billing_type' => $item['billing_type'],
|
||
'sendsms' => $sendsms,
|
||
'create_time' => $invoice['create_time'],
|
||
'invoice_apply_bn' => $invoice['invoice_apply_bn'],
|
||
);
|
||
$data['order_electronic_items'] = $item;
|
||
$channelMdl = app::get('invoice')->model('channel');
|
||
$channel = $channelMdl->dump($invoice['channel_id']);
|
||
$result = kernel::single('erpapi_router_request')->set('invoice',$invoice['shop_id'])->invoice_create_result($data);
|
||
if ($result["rsp"] == "succ") {
|
||
|
||
// 模拟接口回传, 触发更新
|
||
|
||
if(is_string($result['data'])){
|
||
$result['data'] = @json_decode($result['data'],true);
|
||
}
|
||
$result['data']['msg_id'] = $result['msg_id'];
|
||
if ($data['billing_type'] == '2') {
|
||
$result['data']['invoice_apply_bn'] = $invoice['invoice_apply_bn'];
|
||
$result['data']['response']['success'][0]['invoiceType'] = '1';
|
||
}
|
||
kernel::single('erpapi_router_response')->set_node_id($channel['node_id'])->set_api_name('invoice.order.status_update')->dispatch($result['data']);
|
||
}else{
|
||
$result['rsp'] = 'succ';
|
||
$msg = '开票结果查询:'.$result['err_msg'].'('.$result['msg_id'].')';
|
||
$opObj->write_log('invoice_cancel@invoice', $item['id'], '冲红失败:'.$msg);
|
||
//为开票的单据,设置同步状态为开蓝失败
|
||
if ($invoice['is_status'] == '0') {
|
||
$updateData = ['sync'=>'2'];
|
||
}else{
|
||
$updateData = ['sync'=>'5'];
|
||
}
|
||
$invOrderMdl->update($updateData,['id'=>$item['id']]);
|
||
}
|
||
|
||
return array($result['rsp'], $result['err_msg']);
|
||
}
|
||
|
||
/**
|
||
* 电子发票获取url发起方法
|
||
* @param string $shop_id 来源店铺ID
|
||
* @param array $data 获取电子发票url(蓝票或红票)通知数据信息
|
||
* @return array
|
||
*/
|
||
public function getInvoiceUrl($shop_id, &$data)
|
||
{
|
||
$sdf = kernel::single('invoice_event_trigger_data_router')->set_shop_id($shop_id)->getEinvoiceGetUrlRequestParams($data);
|
||
if (!$sdf) return false;
|
||
|
||
$result = kernel::single('erpapi_router_request')->set('invoice',$shop_id)->invoice_get_url($sdf);
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 查询已回传淘宝的电子发票
|
||
* @param string $shop_id 来源店铺ID
|
||
* @param array $data 获取已回传淘宝的电子发票通知数据信息
|
||
* @return array
|
||
*/
|
||
public function getEinvoiceInfo($shop_id, &$data)
|
||
{
|
||
$result = kernel::single('erpapi_router_request')->set('invoice',$shop_id)->invoice_get_info($data);
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 回流天猫前 电子发票状态更新
|
||
* @param string $shop_id 来源店铺ID
|
||
* @param array $data ERP在给tmall开电子发票蓝票和红票前 需要调用此接口把开票状态同步给tmall
|
||
*/
|
||
public function einvoicePrepare($shop_id, &$data)
|
||
{
|
||
$result = kernel::single('erpapi_router_request')->set('invoice',$shop_id)->invoice_einvoice_prepare($data);
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 电子发票回流天猫
|
||
* @param string $shop_id 来源店铺ID
|
||
* @param array $data 电子发票回流天猫 通知数据信息
|
||
*/
|
||
public function uploadTmall($shop_id, &$data)
|
||
{
|
||
$result = kernel::single('erpapi_router_request')->set('invoice',$shop_id)->invoice_upload_tmall($data);
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 开票上传
|
||
*
|
||
* @param int $item_id
|
||
* @return void
|
||
* @author
|
||
**/
|
||
public function upload($item_id, $sync = false)
|
||
{
|
||
$eOrderMdl = app::get('invoice')->model('order');
|
||
$eItemMdl = app::get('invoice')->model('order_electronic_items');
|
||
|
||
$electronic = $eItemMdl->dump($item_id);
|
||
|
||
if ($electronic['upload_tmall_status'] == '2') return array('rsp'=>'succ');
|
||
|
||
$invoice = $eOrderMdl->dump($electronic['id']);
|
||
|
||
if (!in_array($invoice['sync'], array('3','6'))) return array('rsp'=>'fail','msg'=>'尚未同步开票结果');
|
||
|
||
$sdf = kernel::single('invoice_event_trigger_data_router')->set_shop_id($invoice['shop_id'])->getUploadParams($invoice,$electronic);
|
||
|
||
if (!$sdf) return false;
|
||
|
||
$result = kernel::single('erpapi_router_request')->set('shop',$invoice['shop_id'])->invoice_upload($sdf, $sync);
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* 创建板式文件
|
||
* @Author: XueDing
|
||
* @Date: 2024/8/12 3:59 PM
|
||
* @param $shop_id
|
||
* @param $data
|
||
* @return mixed
|
||
*/
|
||
public function createPdfFile($shop_id, &$data)
|
||
{
|
||
$dataLib = kernel::single('invoice_event_trigger_data_router')->set_shop_id($shop_id);
|
||
|
||
$sdf = $dataLib->getEinvoiceCreateFileRequestParams($data);
|
||
|
||
$result = kernel::single('erpapi_router_request')->set('invoice',$shop_id)->invoice_createPdfFile($sdf);
|
||
|
||
return $result;
|
||
}
|
||
}
|