<?php
/**
* Created by PhpStorm.
* User: lxd
* Date: 2019/12/30
* Time: 11:22
* Comm:
*/
namespace Api\Controller;
use Common\Lib\Ts\TsPackage;
use Common\Logic\CountryLogic;
use Common\Logic\DeviceLogic;
use Common\Logic\GoodsLogic;
use Common\Logic\IslandLogic;
use Common\Logic\PartnerGoodsOrderLogic;
use Common\Logic\PartnerGoodsSonorderLogic;
use Common\Logic\PartnerLogic;
use Common\Logic\SimcardLogic;
use Common\Model\DataPackageModel;
use Common\Model\GoodsModel;
use Common\Model\PartnerModel;
use Partner\Logic\LeaseLogic;
use Think\Controller;
use Think\Exception;
use Think\Log;
use Think\Model;
class ShopifyNoticeController extends Controller
{
private $_param;
private $_paramArr;
private $_header = [
'HTTP_X_SHOPIFY_TEST' => 'false',
'HTTP_X_SHOPIFY_HMAC_SHA256' => '',
];
private $_logque;
private $_sign = '33ee5426dad7acd783862018ec04af35069f2ed0f913b2ff486f95432b2e02f7';
private $_self_partner = 1; //shopify的合作商id,订单归属合作商
private $_partner;
private $_api = [
'key' => '951d7d219e283094adf901a6640a8a42',
'pwd' => '207fe05963cc8c4a8559c65ecec3e417',
'url' => 'test-uro.myshopify.com/admin/api/',
'version' => '2020-01',
'authorization' => ''
];
private $_curl;
private $_cityToCollectionRedisKey = "ShopifyNotice:cityToCollection";
// private $_productToCoolectRedisKey = "ShopifyNotice:productToCoolect";
private $_productStatus = "ShopifyNotice:productStatus";
private $_productToArea = "ShopifyNotice:productToArea"; //最后一个逗号值是商品类型
private $_shopifyCurlQueue = "ShopifyNotice:curlQueue"; //curl放队列里面 单个执行
private $_curlLastErr = '';
private $_skipCheckHeaderAction = ['getcustomcollections'];
const DEVICEFLOW = 'DEVICE_FLOW'; //设备流量
const SIMFLOW = 'SIM_FLOW'; //sim流量
const SIMOTAFLOW = 'SIM_FLOW_AND_OTA_CARD'; //sim流量 + ota卡
const SIMONCEFLOW = 'SIM_FLOW_AND_ONCE_CARD'; //sim流量 + 非ota卡
CONST ESIM = 'ESIM'; //esim 类型
const TAGOTA = 'plus ota card';
const TAGONCE = 'plus once card';
const HANDLESIM = 2;
CONST HANDLEDEVICE = 3;
CONST HANDLEOTA = 4;
CONST HANDLEONCE = 5;
CONST HANDLE_ESIM = 6;
public function __construct( $skipPartner = false )
{
parent::__construct();
$this->_param = file_get_contents( 'php://input' );
$this->_paramArr = json_decode( $this->_param, true );
$this->_header = $_SERVER;
if( $this->_param )
$this->_setLog( "receive param == {$this->_param}, header == " . json_encode( $this->_header ) );
if( !APP_DEBUG ) {
$this->_sign = '//online data';
$this->_api = [
//online shopify api data
];
}
$this->_curl = new \Curl();
$this->_api['authorization'] = base64_encode( "{$this->_api['key']}:{$this->_api['pwd']}" );
if( !in_array( strtolower( ACTION_NAME ), $this->_skipCheckHeaderAction ) )
$this->_checkParam();
}
public function getCurlQueueName()
{
return $this->_shopifyCurlQueue;
}
public function getCustomCollections( $param )
{
if( !isset( $param['ids'] ) ) {
return [];
}
$proIds = explode( ',', $param['ids'] );
array_filter( $proIds );
if( empty( $proIds ) )
return [];
//读取商品对应的city ids
$redis = getRedis();
$reret = $redis->hMGet( $this->_productToArea, $proIds );
if( empty( $reret ) )
return [];
$cityToCollection = [];
$tempCityToCollection = $redis->hGetAll( $this->_cityToCollectionRedisKey );
foreach( $tempCityToCollection as $cid => $collInfo ) {
$tempCollInfo = json_decode( $collInfo,true );
if( empty( $tempCollInfo ) )
continue;
$cityToCollection[$cid] = $tempCollInfo['id'];
}
$return = [];
foreach( $reret as $pid => $areas ) {
$tempArea = explode(',', $areas );
array_pop( $tempArea ); //弹出商品类型
if( count( $tempArea ) < 1 ) //出错了,忽略掉
continue;
$tempAreaCollIds = [];
foreach( $tempArea as $_cid ) {
if( isset( $cityToCollection[$_cid] ) ) {
$tempAreaCollIds[] = $cityToCollection[$_cid];
}
}
$return[$pid] = $tempAreaCollIds;
}
return $return;
}
/**
* 订单支付成功后的通知
* author liuxiaodong
* date 2020/1/2 16:53
*/
public function payed()
{
try {
ignore_user_abort( true );
if( !APP_DEBUG && $this->_header['HTTP_X_SHOPIFY_TEST'] === 'true' ) {
$this->_setLog( '正式服务器上收到了测试的shopify信息,程序停止!请检查! HTTP_X_SHOPIFY_TEST = ' . $this->_header['HTTP_X_SHOPIFY_TEST'], Log::ERR );
}
if( $this->_paramArr['financial_status'] != 'paid' ) {
$this->_setLog( '订单状态异常,非paid !!' . $this->_paramArr['financial_status'] );
//流量商品需配置该信息,其他的商品,mos忽略
exit;
}
$imeis = $cards = $all = [];
// if( empty( $this->_paramArr['note_attributes'] ) ){
// $this->_setLog( '未收到 note_attributes 信息,没有需要同步的信息' . json_encode( $this->_paramArr['note_attributes'] ) );
// //流量商品需配置该信息,其他的商品,mos忽略
// exit;
// }
$productsDeivce = [];
foreach ( $this->_paramArr['line_items'] as $line_item) {
if( isset( $line_item['properties'] ) ) {
foreach( $line_item['properties'] as $prod ) {
$prod['type'] = $prod['name'];
$prod['name'] = "imei{$line_item['product_id']}";
$productsDeivce[] = $prod;
}
}
}
if( empty( $productsDeivce ) ){
$this->_setLog( '未收到 productsDeivce 信息,没有需要同步的信息' . json_encode( $productsDeivce ) );
//流量商品需配置该信息,其他的商品,mos忽略
exit;
}
$this->_setLog( ' productsDeivce === ' . json_encode( $productsDeivce ) );
if( $this->_paramArr['fulfillment_status'] == 'fulfilled' ) {
$this->_setLog( '该商品已发货' . json_encode( $this->_paramArr['fulfillment_status'] ) );
//流量商品需配置该信息,其他的商品,mos忽略
exit;
}
$redis = getRedis();
$rekey = "ShopifyNotice:payed" . $this->_paramArr['token'];
$ret = $redis->setnx( $rekey, 1 );
if( !$ret ) {
$this->_setLog( '该token已被处理,忽略' . json_encode( $this->_paramArr['token'] ) );
//token校验
exit;
}
$redis->expire( $rekey, 30 * 86400 );
$skus = [];
$is_esim = 0;
$_esim_num = '';
foreach ( $productsDeivce as $item ) {
$productId = trim( $item['name'], 'imei' );
$valInfo = [];
foreach( $this->_paramArr['line_items'] as $prod ) {
if( $prod['product_id'] == $productId ) {
$valInfo = [
'name' => $prod['name'],
'sku' => $prod['sku'],
'quantity' => $prod['quantity'],
'id' => $prod['id']
];
$skus[] = $prod['sku'];
break;
}
}
if( $item['type'] == 'esim' ) {
$is_esim = 1;
for( $_i = 0; $_i < $valInfo['quantity']; $_i++ ) {
if( !isset( $all[$_esim_num] ) )
$all[$_esim_num] = [$valInfo];
else
$all[$_esim_num][] = $valInfo;
}
}else {
//simcard ,macaroon 使用 imei
if( strlen( $item['value'] ) == 20 )
$cards[] = $item['value'];
else
$imeis[] = $item['value'];
if( !isset( $all[$item['value']] ) )
$all[$item['value']] = [$valInfo];
else
$all[$item['value']][] = $valInfo;
}
}
$this->_setLog( "设备商品信息:imeis== " . json_encode( $imeis ) . " ;; cards == " . json_encode( $cards ) . " ;; is_esim == " . $is_esim );
if( $is_esim ) {
$this->_setLog( 'esmi 类型;开始处理,无需检查设备信息 。。 valInfo == ' . json_encode($valInfo) );
}else {
if( empty( $imeis ) && empty( $cards ) ) {
$ret = $this->_addNoteToOrder( $this->_paramArr['id'], 'MOS ERROR: 无设备,无卡,失败' );
if( $ret )
$this->_setLog( '发送shopify请求成功,ret' . $ret );
$this->_setLog( '无设备,无卡,请检查', Log::ERR );
}
}
//验证设备信息
if( $imeis ) {
if( !$this->_checkImeis( $imeis ) ) {
$ret = $this->_addNoteToOrder( $this->_paramArr['id'], 'MOS ERROR: 未找到有关的设备信息,失败' );
if( $ret )
$this->_setLog( '发送shopify请求成功,ret' . var_export($ret, true ) );
$this->_setLog( '服务器检查imei失败,请查看并更新错误!', Log::ERR );
}
}
if( $cards ) {
if( !$this->_checkCards( $cards ) ) {
$ret = $this->_addNoteToOrder( $this->_paramArr['id'], 'MOS ERROR: 未找到有关的卡信息,失败' );
if( $ret )
$this->_setLog( '发送shopify请求成功,ret' . var_export($ret, true ) );
$this->_setLog( '服务器检查imei失败,请查看并更新错误!', Log::ERR );
}
}
$this->_setLog( '验证设备信息成功,开始验证商品...' );
//获取商品信息
$newSkuInfo = [];
if( $skus ) {
$skuInfo = $this->_checkSkus( $skus );
if( !$skuInfo ) {
$ret = $this->_addNoteToOrder($this->_paramArr['id'], 'MOS ERROR: 未找到有关的商品信息,失败');
if ($ret)
$this->_setLog('发送shopify请求成功,ret' . var_export($ret, true ));
$this->_setLog( '服务器检查套餐失败,请查看并更新错误!skus = ' . var_export($skus, true ), Log::ERR );
}
foreach( $skuInfo as $item ) {
if( !isset( $item['validay'] ) ){
$item['validay'] = $item['validity'];
}
$newSkuInfo[$item['sku']] = $item;
}
unset( $skuInfo );
}else {
$ret = $this->_addNoteToOrder( $this->_paramArr['id'], 'MOS ERROR: 商品没有配置SKU,失败' );
if( $ret )
$this->_setLog( '发送shopify请求成功,ret' . var_export($ret, true ) );
$this->_setLog( '商品没有配置SKU信息,请检查', Log::ERR );
}
$this->_setLog( '验证商品信息成功,开始同步...' );
$startTime = new \DateTime();
$leaseLogic = new LeaseLogic();
//开始同步
if( $all ) {
$oid = createOrderNumber('SY');
$orderData = $sonOrderData = [];
foreach( $all as $imei => $item ) {
foreach( $item as $ik => $iv ) {
$ginfo = $newSkuInfo[$iv['sku']];
$orderData['gnames'][] = $iv['name'];
$orderData['gshows'][$iv['id']] = [
//data
];
$endTmfd = clone $startTime;
$addDays = $iv['quantity'] * $ginfo['validity'];
$endTmfd->add( new \DateInterval( "P{$addDays}D" ) );
$sonOrderData[] = [//data]
}
}
$gtid = !empty( $imeis) ? GoodsModel::GTFLOW : GoodsModel::GTSIMFLOW;
if( $is_esim ) {
$gtid = GoodsModel::GTESIMFLOW;
}
$addData = [
//data
];
$orderModel = new PartnerGoodsOrderLogic();
$sonOrderModel = new PartnerGoodsSonorderLogic();
$orderModel->startTrans();
if( !$orderModel->add( $addData ) ) {
$orderModel->rollback();
$this->_setLog( '服务器新增主订单失败' . json_encode( $addData ), Log::ERR );
}
if( !$sonOrderModel->addAll( $sonOrderData ) ) {
$orderModel->rollback();
$this->_setLog( '服务器新增子订单失败' . json_encode( $orderData ), Log::ERR );
}
$orderModel->commit();
$this->_setLog( '商品入库成功...' );
$ret = $leaseLogic->_syncTsNew( $oid, [], 0, DataPackageModel::SOURCESHOPIFY );
$str = $ret ? '成功' : '失败';
$node = "MOS已同步[$oid]。结果: {$str}";
if( !$ret ) {
$this->_addNoteToOrder( $this->_paramArr['id'], $node );
$this->_setLog( 'MOS 同步失败,不发货...' );
$this->_setLog( '执行完毕...' );
return true;
}
$this->_setLog( '开始发货...' );
$esimList = [];
if( $is_esim ) {
//esim 卡需要获取卡的二维码信息
$esimList = (new PartnerGoodsSonorderLogic())->getEsimCardQcode( $oid );
if( !$esimList ) {
$this->_setLog( '开始发货...,esim 类型,获取二维码失败,发货失败' );
$this->_addNoteToOrder( $this->_paramArr['id'], $node . ' ;; 二维码读取失败,发货失败' );
return false;
}
}
$flag = true;
foreach( $this->_paramArr['line_items'] as $item ) {
if( !$this->_fulfillment( $this->_paramArr['id'], $item['id'], $item['variant_id'], $node, $item['sku'], $esimList ) )
$flag = false;
}
if( $flag )
$this->_setLog( '发货成功...' );
else
$this->_setLog( '发货失败...' );
$this->_setLog( '开始写note...' );
$this->_addNoteToOrder( $this->_paramArr['id'], $node );
$this->_setLog( '执行完毕...' );
}
}catch ( \Exception $e ) {
$this->_setLog( '执行过程出异常了...' . $e, Log::ERR );
}
}
private function _esimJob( $valInfo, $skus )
{
$this->_setLog( '开始esmi发货处理....' . json_encode( ['valInfo' => $valInfo, 'skus' => $skus ] ) );
}
//商品创建
public function prodUpdate()
{
if( !isset( $this->_paramArr['variants'] ) ) {
$this->_setLog( '商品没有variants信息,忽略', Log::ERR );
}
$skus = [];
foreach( $this->_paramArr['variants'] as $item ) {
$skus[] = $item['sku'];
}
$md5Sku = md5( json_encode( $skus ) . $this->_param['tags'] );
$redis = getRedis();
$proSt = $redis->hGet( $this->_productStatus, $this->_paramArr['id'] );
if( $this->_paramArr['published_at'] ) {
if( $proSt == $md5Sku ) {
$this->_setLog( '商品sku未更新,商品状态未更新,忽略', Log::WARN );
return;
}else {
$this->_setLog( '开始下架原商品。。。' );
$this->prodDeletion( $this->_paramArr['id'] );
$this->_setLog( '下架完成。。。' );
}
}else {
//下架
$this->_setLog( '开始下架商品。。。' );
$this->prodDeletion( $this->_paramArr['id'] );
return;
}
//获取商品信息
$model = new GoodsLogic();
$glist = $model->getListSku( $skus, $this->_getPartners() );
if( !$glist ) {
$this->_setLog( '未获取到sku对应的信息,忽略该商品', Log::ERR );
}
$this->_setLog( "读取sku成功。" );
$customCollect = $this->_getCustomCollections();
$collect = $customCollectMof = [];
$productArea = [];
foreach( $glist as $ginfo ) {
if( empty( $ginfo['_area'] ) ) {
$this->_setLog( "改sku{$ginfo['sku']}没有对应的区域信息,忽略。" );
continue;
}
foreach( $ginfo['_area'] as $cityId ) {
$sim = $dev = $simOta = $simOnce = $esim = 0;
$_self_gtype = null;
if( $ginfo['gtid'] == GoodsModel::GTFLOW ) {
$dev = 1;
$_self_gtype = self::HANDLEDEVICE;
}else if( $ginfo['gtid'] == GoodsModel::GTSIMFLOW ) {
if( strpos( $this->_paramArr['tags'], self::TAGOTA ) !== false ) {
$simOta = 1;
$_self_gtype = self::HANDLEOTA;
}else if( strpos( $this->_paramArr['tags'], self::TAGONCE ) !== false ) {
$simOnce = 1;
$_self_gtype = self::HANDLEONCE;
}else {
$sim = 1;
$_self_gtype = self::HANDLESIM;
}
}else if( $ginfo['gtid'] == GoodsModel::GTESIMFLOW ) {
$esim = 1;
$_self_gtype = self::HANDLE_ESIM;
}
$this->_setLog( "处理城市id== {$cityId}; sim = {$sim}; dev = {$dev}; simota = {$simOta}; simonce = {$simOnce}; esim = {$esim}; _self_gtype == {$_self_gtype}" );
if( isset( $customCollect[$cityId] ) ) {
$_customCollectArr = json_decode( $customCollect[$cityId], true );
$_customCollectId = $_customCollectArr['id'];
$_customCollectHandle = explode('_', $_customCollectArr['handle'] );
$_customCollectHandle[self::HANDLESIM] = ( (int)$_customCollectHandle[self::HANDLESIM] ) + $sim;
$_customCollectHandle[self::HANDLEDEVICE] = ( (int)$_customCollectHandle[self::HANDLEDEVICE] ) + $dev;
$_customCollectHandle[self::HANDLEOTA] = ( (int)$_customCollectHandle[self::HANDLEOTA] ) + $simOta;
$_customCollectHandle[self::HANDLEONCE] = ( (int)$_customCollectHandle[self::HANDLEONCE] ) + $simOnce;
$_customCollectHandle[self::HANDLE_ESIM] = isset( $_customCollectHandle[self::HANDLE_ESIM] ) ? ( (int)$_customCollectHandle[self::HANDLE_ESIM] ) + $esim : $esim;
$collect[] = [
'collect' => [
'product_id' => $this->_paramArr['id'],
'collection_id' => $_customCollectId
]
];
$customCollectMof[$_customCollectId] = [
'custom_collection' => [
'id' => $_customCollectId,
'handle' => implode( '_', $_customCollectHandle )
]
];
$productArea[] = $cityId;
// $customCollectRedis[$cityId] = json_encode( [ 'id' => $_customCollectId, 'handle' => implode( '_', $_customCollectHandle ) ] );
}else {
$collection = $this->_createCollection( $cityId, $sim, $dev );
if( isset( $collection['id'] ) ){
$collect[] = [
'collect' => [
'product_id' => $this->_paramArr['id'],
'collection_id' => $collection['id']
]
];
$productArea[] = $cityId;
}else {
$this->_setLog( "城市{$cityId}请求createCollection 失败,建立商品关系失败", Log::WARN );
continue;
}
// $customCollectRedis[$cityId] = json_encode( [ 'id' => $collection['id'], 'handle' => $collection['handle'] ] );
}
}
}
if( $collect ) {
$this->_setLog( "开始请求 collect 信息" );
$this->_createCollect( $collect );
}
if( $customCollectMof ) {
$this->_setLog( "有需要更新的custom collection信息。" );
$this->_mofCollection( $customCollectMof );
}
if( $productArea ) {
$this->_setLog( "设定商品对应的国家id关系。" . json_encode( $productArea ) );
$productArea = array_unique( $productArea );
$redis->hSet( $this->_productToArea, $this->_paramArr['id'], implode( ',', $productArea ) . ',' . $_self_gtype );
}
$productType = '';
switch ( $_self_gtype ) {
case self::HANDLESIM:
$productType = self::SIMFLOW;
break;
case self::HANDLEONCE:
$productType = self::SIMONCEFLOW;
break;
case self::HANDLEOTA:
$productType = self::SIMOTAFLOW;
break;
case self::HANDLEDEVICE:
$productType = self::DEVICEFLOW;
break;
case self::HANDLE_ESIM:
$productType = self::ESIM;
break;
}
$redis->rPush( $this->_shopifyCurlQueue, json_encode( [
'className' => self::class,
'method' => 'mofProductJob',
'param' => [
'product' => [
'id' => $this->_paramArr['id'],
'product_type' => $productType
]
],
'doTimes' => 0
] ) );
$redis->hSet( $this->_productStatus, $this->_paramArr['id'], $md5Sku );
$this->_setLog( "执行完毕。ok" );
}
public function prodDeletion( $id = null )
{
if( !$id )
$id = $this->_paramArr['id'];
if( !$id ) {
$this->_setLog( "id 「{$id}」 为空。忽略。。" );
return;
}
$redis = getRedis();
//清理管连关系
$area = $redis->hGet( $this->_productToArea, $id );
if( !$area ) {
$this->_setLog( "未找到商品的关联区域信息。忽略。。" );
return;
}
$redis->hDel( $this->_productToArea, $id );
$areaArr = explode( ',', $area );
$gtype = array_pop( $areaArr );
$this->_setLog( "处理区域与custom collection关系" );
$customCollectMof = [];
foreach( $areaArr as $cityId ) {
$customCollect = $redis->hget( $this->_cityToCollectionRedisKey, $cityId );
if( $customCollect ) {
$_tmp = json_decode( $customCollect, true );
$_handle = explode( '_', $_tmp['handle'] );
switch ( $gtype ) {
case self::HANDLESIM:
$_handle[self::HANDLESIM] = ( (int)$_handle[self::HANDLESIM] ) - 1;
break;
case self::HANDLEONCE:
$_handle[self::HANDLEONCE] = ( (int)$_handle[self::HANDLEONCE] ) - 1;
break;
case self::HANDLEOTA:
$_handle[self::HANDLEOTA] = ( (int)$_handle[self::HANDLEOTA] ) - 1;
break;
case self::HANDLEDEVICE:
$_handle[self::HANDLEDEVICE] = ( (int)$_handle[self::HANDLEDEVICE] ) - 1;
break;
case self::HANDLE_ESIM:
$_handle[self::HANDLE_ESIM] = ( (int)$_handle[self::HANDLE_ESIM] ) - 1;
break;
}
$_tmp['handle'] = implode( '_', $_handle );
$customCollectMof[] = [
'custom_collection' => [
'id' => $_tmp['id'],
'handle' => $_tmp['handle']
]
];
$_tmp = null;
}
}
if( $customCollectMof )
$this->_mofCollection( $customCollectMof );
$redis->hSet( $this->_productStatus, $id, '' );
}
private function sendRequest( $method, $urlExtend, $data = '', $header = [], $needResHeader = false )
{
static $tryTimes = 1;
$tmpHeader = ['Content-Type:application/json','Cache-Controller: max-age=0', 'Authorization: Basic ' . $this->_api['authorization']];
if( is_array( $data ) && !empty( $data ) ) {
$data = json_encode( $data );
$tmpHeader[] = 'Content-Length: ' . strlen( $data );
}else {
$data = (string)$data;
}
if( !empty( $header ) ) {
$tmpHeader = array_merge( $tmpHeader, $header );
}
$redis = getRedis();
$url = "https://{$this->_api['key']}:{$this->_api['pwd']}@{$this->_api['url']}{$this->_api['version']}/{$urlExtend}";
$this->_setLog( '开始curl '. $method .' ,url == ' . $url . ',, param == ' . $data );
$ret = $this->_curl->execute( $method, $url, $data, '', $tmpHeader, '', '', $needResHeader );
if( is_array( $ret ) || $ret === false ) {
$tryTimes++;
if( $tryTimes >= 1 ) {
$this->_curlLastErr = "send curl error ..";
if( isset( $ret[1] ) )
$this->_curlLastErr .= "{$ret[1]}";
$this->_setLog( 'curl 请求shopify失败,请检查! ' . json_encode( $ret ), Log::WARN );
//添加到重试队列
$redis->rPush( $this->_shopifyCurlQueue, json_encode( [
'className' => self::class,
'method' => 'curlRedoJob',
'param' => [
'method' => $method,
'url' => $urlExtend,
'data' => $data,
'header' => $header,
'needResHeader' => $needResHeader
],
'doTimes' => 0
] ) );
return false;
}else {
return $this->sendRequest( $method, $urlExtend, $data, $header, $needResHeader );
}
}
$deRet = json_decode( $ret, true );
if( $needResHeader ) {
if( isset( $deRet['ret']['errors'] ) ) {
$this->_curlLastErr = $ret;
$this->_setLog( '请求成功,但是返回了失败,.' . $ret, Log::WARN );
return false;
}
}else {
if( isset( $deRet['errors'] ) || isset( $deRet['error'] ) ) {
$this->_curlLastErr = $ret;
$this->_setLog( '请求成功,但是返回了失败,.' . $ret, Log::WARN );
return false;
}
}
$this->_setLog( '请求成功了,' . $ret );
return $deRet;
}
public function curlRedoJob( $data )
{
$ret = $this->sendRequest( $data['method'], $data['url'], $data['data'], $data['header'], $data['needResHeader'] );
if( !$ret ) {
return false;
}
return true;
}
//给订单添加note
private function _addNoteToOrder( $oid, $note )
{
$param = ['order' => [
'id' => $oid,
'note' => $note
]];
$ret = $this->sendRequest( 'PUT', "orders/{$oid}.json", $param );
if( !$ret ) {
$this->_setLog( '请求_addNoteToOrder失败了' . var_export( $ret, true ), Log::ERR );
}
return $ret;
}
private function _getCustomCollections( $force = false )
{
$ret = [];
$redis = getRedis();
$ret = $redis->hGetAll( $this->_cityToCollectionRedisKey );
if( $ret && !$force )
return $ret;
$url = 'custom_collections.json?limit=250';
while( true ) {
$list = $this->sendRequest( 'GET', $url, '', [] ,true );
$retArr = json_decode( $list['ret'], true );
if( empty( $retArr['custom_collections'] ) ) {
$this->_setLog( '获取CustomCollections失败,请检查.' . var_export( $list, true ), Log::WARN );
return [];
}
foreach( $retArr['custom_collections'] as $item ) {
// $tmpPatten = "/<input\stype=\"hidden\"\svalue='(.*?)'>/";
// $match = [];
// if( !preg_match( $tmpPatten, $item['body_html'], $match ) ) {
// continue;
// }
// $storeInfo = json_decode( $match[1], true );
// $id = $storeInfo['id'];
// if( !$id )
// continue;
$_tmp = explode( '_', $item['handle'] );
if( !isset( $_tmp[1] ) )
continue;
$id = $_tmp[1];
$ret[$id] = json_encode( [ 'id' => $item['id'], 'handle' => $item['handle'] ] );
}
$linkPattern = "/link\:\s<(.*)>/U";
$match = [];
if( preg_match( $linkPattern, $list['header'],$match ) ) {
$url = "custom_collections.json?" . parse_url( $match[1] )['query'];
}else {
break;
}
}
$redis->hMset( $this->_cityToCollectionRedisKey, $ret );
return $ret;
}
public function initCreateCollection()
{
$this->_createCollection( 'init' );
}
private function _createCollection( $ids = '', $sim = 0, $dev = 0, $ota = 0, $noOta = 0 )
{
$isLand = [
1 => 'America',
2 => 'Oceania',
4 => 'Africa',
5 => 'Europe',
6 => 'Asia'
];
if( !$ids )
return false;
$where = [];
if( $ids ) {
if( $ids === 'init' ) {
$where = [];
}else
$where['ids'] = $ids;
}
$country = new CountryLogic();
$list = $country->getCountryList( $where );
foreach( $list as $item ) {
if( empty( $item['english_language'] ) ) {
$this->_setLog( '城市' . $item['id'] . '没有英文名称!!!', Log::WARN );
continue;
}
$continentName = isset( $isLand[$item['continent_id']] ) ? $isLand[$item['continent_id']] : 'other';
if( $continentName == 'other' ) {
echo $item['name'] . "<br />";
}
// $json = json_encode( [
// 'id' => $item['id'],
// 'sim' => $sim,
// 'dev' => $dev,
// 'cn' => $item['name'],
// 'jp' => $item['ja_name']
// ], JSON_UNESCAPED_UNICODE );
$handle = strtolower( $continentName ) . "_{$item['id']}_{$sim}_{$dev}_{$ota}_{$noOta}";
$param = [
'custom_collection' => [
'title' => strtolower( $item['english_language'] ),
'handle' => $handle,
]
];
$ret = $this->sendRequest( 'POST', 'custom_collections.json', $param );
if( !$ret ) {
$this->_setLog( '城市' . $item['id'] . '建立custom_collections失败!!!', Log::WARN );
return false;
}
$redis = getRedis();
$redis->hSet( $this->_cityToCollectionRedisKey, $item['id'], json_encode( [ 'id' => $ret['custom_collection']['id'], 'handle' => $handle ] ) );
if( $ids === 'init' )
continue;
else
return $ret['custom_collection'];
}
return false;
}
private function _mofCollection( $data )
{
$redis = getRedis();
foreach( $data as $item ) {
// $ret = $this->sendRequest( 'PUT', 'custom_collections/' . $item['custom_collection']['id'] . '.json', $item );
// if( !$ret ) {
// $this->_setLog( "更新custom collection 失败" . var_export( $item, true ) );
// continue;
// }
$redis->rPush( $this->_shopifyCurlQueue, json_encode( [
'className' => self::class,
'method' => 'mofCollectionJob',
'param' => $item,
'doTimes' => 0
] ) );
$handleArr = explode( '_', $item['custom_collection']['handle'] );
$redis->hSet( $this->_cityToCollectionRedisKey, $handleArr[1], json_encode( ['id' => $item['custom_collection']['id'] , 'handle' => $item['custom_collection']['handle'] ] ) );
}
}
public function mofCollectionJob( $data )
{
$ret = $this->sendRequest( 'PUT', 'custom_collections/' . $data['custom_collection']['id'] . '.json', $data );
if( !$ret ) {
return false;
}
return true;
}
public function mofProductJob( $data )
{
$ret = $this->sendRequest( 'PUT', "products/{$data['product']['id']}.json", $data );
if( !$ret ) {
return false;
}
return true;
}
private function _createCollect( $data )
{
$redis = getRedis();
foreach( $data as $item ) {
$redis->rPush( $this->_shopifyCurlQueue, json_encode( [
'className' => self::class,
'method' => 'createCollectJob',
'param' => $item,
'doTimes' => 0
] ) );
// $ret = $this->sendRequest( 'POST', 'collects.json', $item );
// if( !$ret ) {
// $this->_setLog( "设定商品,collect 关联关系失败" . var_export( $ret, true ) );
// continue;
// }
// $reval = $redis->hGet( $this->_productToCoolectRedisKey, $item['collect']['product_id'] );
// $setVal = "{$ret['collect']['id']}";
// if( $reval )
// $setVal .= ",{$reval}";
// $redis->hSet( $this->_productToCoolectRedisKey, $item['collect']['product_id'], $setVal );
}
}
public function createCollectJob( $data )
{
$ret = $this->sendRequest( 'POST', 'collects.json', $data );
if( !$ret ) {
if( strpos( $this->_curlLastErr, 'already exists' ) ) {
return true;
}
return false;
}
return true;
}
/**
private function _delCollect( $productId )
{
$redis = getRedis();
$ret = $redis->hGet( $this->_productToCoolectRedisKey, $productId );
if( !$ret ) {
$this->_setLog( "该商品无collect信息" );
return;
}
$data = explode( ',', $ret );
foreach( $data as $item ) {
$ret = $this->sendRequest( 'DELETE', "collects/{$item}.json" );
if( $ret === false ) {
$this->_setLog( "设定商品,collect 清理关联关系失败" . var_export( $ret, true ) );
continue;
}
}
$redis->hDel( $this->_productToCoolectRedisKey, $productId );
}
*/
//获取商品
private function _fulfillment( $oid, $lineItemId, $variantRestId, &$note, $sku, $esimList = [] )
{
$ret = $this->sendRequest( 'GET', "variants/{$variantRestId}.json" );
if( !$ret ) {
$note .= "\n 获取商品信息异常(variants),发货失败";
$this->_setLog( "variants/{$variantRestId}.json 请求失败。" . var_export( $ret, true ) );
return false;
}
$ret = $this->sendRequest( 'GET', "inventory_levels.json?inventory_item_ids={$ret['variant']['inventory_item_id']}" );
if( !$ret ) {
$note .= "\n 获取商品信息异常(inventory_levels),发货失败";
$this->_setLog( "inventory_levels.json?inventory_item_ids={$ret['variant']['inventory_item_id']} 请求失败。" . var_export( $ret, true ) );
return false;
}
$param = [
'fulfillment' => [
'location_id' => $ret['inventory_levels'][0]['location_id'],
'tracking_number' => null,
'line_items' => [['id' => $lineItemId]]
]
];
if( isset( $esimList[$sku] ) ) {
$tracking_urls = $esimList[$sku];
$param['fulfillment']['tracking_numbers'] = $tracking_urls;
foreach( $tracking_urls as &$_item ) {
$_item = $this->createEsimQrImg( $_item );
}
unset( $_item );
$param['fulfillment']['tracking_urls'] = $tracking_urls;
$param['fulfillment']['tracking_company'] = 'self';
}
$ret = $this->sendRequest( 'POST', "orders/{$oid}/fulfillments.json", $param );
if( !$ret ) {
$note .= "\n 请求发货接口失败,发货失败";
$this->_setLog( "orders/{$oid}/fulfillments.json 请求失败。" . var_export( $ret, true ) );
return false;
}
return true;
}
public function createEsimQrImg( $str )
{
$path = './' . C("UPLOADPATH") . 'qrcode/'; //上传主目录
$file_name = $path . md5( $str ) . '.png';
if (!file_exists($file_name)) {
$QR = new \Common\Lib\Qrcode();
$logo = "./public/images/esim_qr_logo.png";
if (!file_exists($path)) {
mkdir($path, 755, true);
}
$bgImg = "./public/images/esim_qr_bg.png";
$QR->create_with_background($str, $file_name, 'M', 10, $logo, $bgImg);
}
if (file_exists($file_name)) {
$img = $file_name ? 'http://' . $_SERVER['SERVER_NAME'] . '/' . $file_name : '';
}
return $img;
}
public function __call($name, $arguments)
{
// TODO: Implement __call() method.
$data = [
'name' => $name,
'arg' => $arguments
];
$this->_setLog( json_encode( $data ) );
return true;
}
private function _checkImeis( $imeis )
{
$model = new DeviceLogic();
$count = $model->getCountInImei( $this->_partner, $imeis );
if( $count != count( array_unique( $imeis ) ) )
return false;
return true;
}
private function _checkCards( $cards )
{
$model = new SimcardLogic();
$count = $model->getCountInImei( $this->_partner, $cards );
if( $count != count( array_unique( $cards ) ) )
return false;
return true;
}
private function _checkSkus( $skus )
{
$model = new GoodsLogic();
$count = $model->getListSku( $skus, $this->_partner );
if( count( $count ) != count( array_unique( $skus ) ) )
return false;
return $count;
}
private function _getPartners()
{
$partner = new PartnerLogic();
$list = $partner->getSonList( PartnerModel::UROAMING_PARTNER_ID );
return array_keys( $list );
}
//验证来源
private function _checkParam()
{
if( IS_CLI ) {
return true;
}
$hashStr = base64_encode( hash_hmac( 'sha256', $this->_param, $this->_sign, true ) );
if( $this->_header['HTTP_X_SHOPIFY_HMAC_SHA256'] !== $hashStr ) {
$this->_setLog( '服务器校验来源异常,程序停止!请检查!', Log::ERR );
return false;
}
$this->_setLog( '检查参数合法性成功' );
return true;
}
private function _setLog( $msg, $level = Log::NOTICE )
{
if( !$this->_logque instanceof \SplQueue )
$this->_logque = new \SplQueue();
$this->_logque->enqueue( $msg . PHP_EOL );
if( $level == Log::ERR ) {
//send mail
exit;
}
}
public function __destruct()
{
if( $this->_logque instanceof \SplQueue ) {
$msg = '';
while( !$this->_logque->isEmpty() ) {
$msg .= $this->_logque->dequeue();
}
Log::write( $msg, Log::NOTICE, '', durableLog( 'api-shopify' ) );
}
}
public function test()
{
$model = new SimcardLogic();
var_dump( $model->getEsimEmpty( 2, [1]));
}
}