您的位置:首页 > 编程语言 > PHP开发

php pthreads 获取货运号代码实例

2015-12-12 12:09 645 查看
首先安装php pthreads

安装参看:http://blog.csdn.net/terry_water/article/details/50252611

安装完成后就可以使用多线程了

1. 多线程方法,继承\Thread ,构造方法中new好下面要使用的对象,run方法写好要执行的代码。

<?php
/*
根据国家和订单金额,选择货运公司,此功能是通过console跑的脚本
*/
namespace myapp\code\core\Erp\Sales\helper;
use Yii;
use myapp\code\core\Erp\Sales\helper\Shippingpthreads;
use myapp\code\core\Erp\Sales\helper\shipping_pthreads\Bilishi;
use myapp\code\core\Erp\Sales\helper\shipping_pthreads\DHL;
use myapp\code\core\Erp\Sales\helper\shipping_pthreads\Eyoubao;
use myapp\code\core\Erp\Sales\helper\shipping_pthreads\SahprShip;
use myapp\code\core\Erp\Sales\helper\shipping_pthreads\Sf;
use common\models\core\CSFAU;
use backend\models\core\XML2Array;
use backend\models\core\Array2XML;
class TrackOrderPthreads extends \Thread
{
public $order;
public $data;
public $Shippingpthreads;

public $bilishi;
public $dhl;
public $eyoubao;
public $SahprShip;
public $sf;
public $csfau;
public $XML2Array;
public $Array2XML;

public function __construct($order)
{
# 下面程序使用的对象,必须在构造方法中实例化,不可以在调用的对象中new对象,会报错
$this->order = $order;
$this->Shippingpthreads = new Shippingpthreads;

$this->bilishi = new bilishi;
$this->dhl = new DHL;
$this->eyoubao = new Eyoubao;
$this->SahprShip = new SahprShip;
$this->sf = new Sf;
$this->csfau = new CSFAU;
$this->XML2Array = new XML2Array;
$this->Array2XML = new Array2XML;
}

public function run()
{

if(($order = $this->order)){

#初始化对象
$bilishi = $this->bilishi;
$dhl = $this->dhl ;
$eyoubao = $this->eyoubao;
$SahprShip = $this->SahprShip;
$sf = $this->sf;

$Shippingpthreads = $this->Shippingpthreads;
$csfau = $this->csfau;
$XML2Array = $this->XML2Array;
$Array2XML = $this->Array2XML;

$BilishiAccount = 'sns:dfdost';

$shipping_company = $order['shipping_company'];

if($shipping_company == $Shippingpthreads::SF_PINGYOU_A2){
# 在sf对象中使用的所有对象,必须在本类的构造方法new好,并传递过去,不能再$sf这个对象中进行new
# 对于静态方法,只有new之后才能使用,不可以使用没有new的类静态方法
$this->data = $result = $sf->getSfShippingNoByOrder($order,'A2',$csfau,$Shippingpthreads,$XML2Array);
}else if($shipping_company == $Shippingpthreads::SF_GUOJI_A1){
$this->data = $result = $sf->getSfShippingNoByOrder($order,'A1',$csfau,$Shippingpthreads,$XML2Array);

}else if($shipping_company == $Shippingpthreads::SF_PINGYOU_A6){
$this->data = $result = $sf->getSfShippingNoByOrder($order,'A6',$csfau,$Shippingpthreads,$XML2Array);
}else if($shipping_company == $Shippingpthreads::DHL){
$this->data = $result = $dhl->getDHLShippingNoByOrder($order,$Shippingpthreads);
}else if($shipping_company == $Shippingpthreads::PX_EMS_C1){
# wish 需要把onfancy 改成wish
#$order['shipping_company'] = $Shippingpthreads::PX_EMS_C1;
//$this->data = $result = $SahprShip->getSahprTrackNum($order,"onfancy",$Shippingpthreads);

}else if($shipping_company == $Shippingpthreads::PX_XJP_B1){
#$order['shipping_company'] = $Shippingpthreads::PX_XJP_B1;
$this->data = $result = $SahprShip->getSahprTrackNum($order,"onfancy",$Shippingpthreads);
# 判断是否是比利时
}else if($shipping_company == $Shippingpthreads::BILISHI){
$this->data = $bilishi->getBilishiShippingNoByOrder($order,$BilishiAccount,$Shippingpthreads);

}else if($shipping_company == $Shippingpthreads::E_YOUBAO){
$this->data = $result = $eyoubao->getEyoubaoShippingNoByOrder($order,$Shippingpthreads,$XML2Array,$Array2XML);
}
}
}

}


3. 对象sf的文件代码:(其他货运方式,不展示了):

<?php
/*
顺丰
产品重量使用的是product weight 75行
总重量用的 self::ORDER_WEIGHT 97行
价格用的是产品的价格 74行
*/
namespace myapp\code\core\Erp\Sales\helper\shipping_pthreads;
use Yii;
use backend\block\Blockbase;
use backend\models\core\XML2Array;
use myapp\code\core\Erp\Sales\models\Salesorderitem;
use myapp\code\core\Erp\Sales\helper\Shipping;
use common\models\core\CSFAU;
class Sf
{
const CHECK_PASS = '503FD8BD72BEFF';
const HEAD = '7552';
const ORDER_WEIGHT = 0.8;
const PRODUCT_NO = 1111;
//const EXPRESS_TYPE = 'A1';
const ORDER_EXITST_SF_CODE = '9002';
public $XML2Array;
public function __construct(){

}

# 1.根据订单返回货运号,先通过生成订单号方式,如果返回
# 返回的值: ["status"]=> string(2) "OK"
# ["orderid"]=> string(9) "800055829"
# ["mailno"]=> string(12) "994018593449"
# ["agent_mailno"]=> string(13) "RS281099136NL"
# ["method"]=> string(18) "OrderSearchService"
#
public function getSfShippingNoByOrder($order,$shipping_type,$csfau,$Shippingpthreads,$XML2Array){
$this->XML2Array = $XML2Array;
$csArr = false;
if($shipping_type == "A6"){
$zip = $order['customer_address_zip'];
$csArr = $csfau::getCityStateByZip($zip);
}
$xmlArray = $this->generalSfGetXmlByOrder($order,$shipping_type,$csArr,$Shippingpthreads);
$searchxmlArray = $this->searchSfGetXmlByOrder($order,$shipping_type);
$result = $this->getSfShippingNo($xmlArray,$searchxmlArray);

if(isset($result['agent_mailno'])){
return [
'ack' => 'success',
'trackingNumber' => $result['agent_mailno'] ? $result['agent_mailno'] : $result['mailno'],
'orderNo' => $result['orderid'],
'mailno' => $result['mailno'],
];
}else{
return [
'ack' => 'fail',
'content'=> $result['code'],
];
}

}

# 2.1根据订单生成获取订单号的api xml(soap)-这个传递的xml为生成订单号的xml request
public function generalSfGetXmlByOrder($order,$shipping_type,$csArr,$shipping){
$increment_id = $order['increment_id'];
$now_city = '';
$now_state = '';
if($csArr){
$now_city = $csArr['city'];
$now_state = $csArr['state'];
}

$items = $order['items'];
$Cargo = [];

$items_count = $order['items_count'];
$sigle_price = $shipping::getSingleProductBasePriceByOrderCount($items_count);

if(is_array($items) && !empty($items)){
foreach($items as $item){
$Cargo[] = [
'@attributes' => [
'hscode' =>$this::PRODUCT_NO, //$item['sku'],
'ename' => 'clothing', //substr($item['name'],0,48),
'count' =>(int)$item['qty'],
'amount' => $sigle_price,
'weight' =>$item['weight'] ? $item['weight'] : 0.1,
],
];
}
}

$xmlArray = array(
'@attributes' => array(
'service' => 'OrderService',
'lang' => 'zh-CN'
),
'Head' => $this::HEAD,
'Body' => [
"Order" => [
'@attributes' => [
'orderid' => $increment_id,
'express_type' => $shipping_type,
'd_contact' =>$order['customer_firstname'].' '.$order['customer_lastname'],
'd_mobile' =>$order['customer_telephone'] ,
'd_address' =>$order['customer_address_street1'].' '.$order['customer_address_street2'],
'parcel_quantity' =>$order['items_count'],
'd_country' =>$order['customer_address_country'],

'd_province' =>$now_state ? $now_state : $order['customer_address_state'],
'd_city' =>$now_city ? $now_city : $order['customer_address_city'],
'd_post_code' =>$order['customer_address_zip'],

'j_country ' => 'CN',
'j_province ' => 'guangdong',
'j_city ' => 'shenzhen',
'j_address ' => 'shenzhen',
'j_company' => 'Grandbing Tech',
'j_contact ' => 'Boxing chen',
'j_post_code ' => '518131',
'j_tel ' => '15818680093',

'cargo_total_weight'=>$this::ORDER_WEIGHT,
'returnsign'=>'Y',
'operate_flag'=>1 # 新增并确认订单
//'d_email' =>$order['customer_email'],
],
'Cargo' =>$Cargo,
]
]
);
return $xmlArray;
}

# 2.2如果订单号存在,获取订单号失败后,需要通过查询的方式获取订单号
public function searchSfGetXmlByOrder($order,$shipping_type){

$increment_id = $order['increment_id'];
$xmlArray = array(
'@attributes' => array(
'service' => 'OrderSearchService',
'lang' => 'zh-CN'
),
'Head' => $this::HEAD,
'Body' => array(
"OrderSearch" => array(
'@attributes' => array(
'orderid' => $increment_id,
)
))
);
return $xmlArray ;
}

# 3.通过xml request 获取返回数据
public function getSfShippingNo($xmlArray,$searchxmlArray,$checkword=''){
$result = $this->EncryptionData($xmlArray,$checkword);
$reponseStatus = $result['Response']['Head'];
//如果返回的结果成功,那么通过返回的数据,获取货运号等一些信息
if(strtolower($reponseStatus) === 'ok'){
$data = $this->getSfGeneralShippingNo($result);
return $data;
}else if(strtolower($reponseStatus) === 'err'){
$error = $result['Response']['ERROR'];
$code = $error['@attributes']['code'];
$codeArr = explode(",",$code);
foreach($codeArr as $ce){
$ce = trim($ce);
if($ce == $this::ORDER_EXITST_SF_CODE){
return $this->OrderSearch($searchxmlArray,$checkword);
}
}
return [
'status' => 'error',
'code' => $code,
];

}
}

public function base64($str){ // base64转码

return base64_encode($str);

}

public function _md5($str){ // md5加密并转大写

return strtoupper(md5($str));

}

#4.1 查询订单的方式返回的xml数据,解析出来想要的数据。
public function OrderSearch($searchxmlArray,$checkword=''){
$result = $this->EncryptionData($searchxmlArray,$checkword);

$reponseStatus = $result['Response']['Head'];
$body = $result['Response']['Body'];
$attributes = $body["OrderSearchResponse"]["@attributes"];
$orderId = $attributes["orderid"];
$mailno = $attributes["mailno"];
$agent_mailno =$attributes["coservehawbcode"];

$oscode = $attributes["oscode"];
$destcode = $attributes["destcode"];
return [
'status'=>$reponseStatus,
'orderid' =>$orderId,
'mailno' => $mailno,
'agent_mailno'=>$agent_mailno,

'method'=>'OrderSearchService',
'oscode'=>$oscode,
'destcode'=>$destcode,
];

}

#4.1 生成订单的方式返回的xml数据,解析出来想要的数据。
public function getSfGeneralShippingNo($result){
$reponseStatus = $result['Response']['Head'];
$body = $result['Response']['Body'];
$attributes = $body["OrderResponse"]["@attributes"];

$orderId = $attributes["orderid"];
$mailno = $attributes["mailno"];
$agent_mailno =$attributes["agent_mailno"];
return [
'status'=>$reponseStatus,
'orderid' =>$orderId,
'mailno' => $mailno,
'agent_mailno'=>$agent_mailno,
'method'=>'OrderService',
];

}

/**
* 加密方法
* @param $xml XML字符串
* @param $checkword 密钥
*/

public function EncryptionData($xmlArray,$checkword=''){
if(!$checkword){
$checkword = $this::CHECK_PASS;
}
$xml = $this->array2xml($xmlArray,"Request");
$md5Data = $this->_md5($xml.$checkword);

$verifyCode = $this->base64($md5Data);

$result = $this->callWebServer($xml,$verifyCode); // 调用webserver
$XML2Array = $this->XML2Array;
$array = $XML2Array::createArray($result);
return $array;
}

/**
* 调用webserver
* @param $xml XML字符串
* @param $verifyCode 加密后的字符串
* 返回xml格式
*/

public function callWebServer($xml,$verifyCode){

$client = new \SoapClient("http://www.sfb2c.com:8003/CBTA/ws/sfexpressService?wsdl");

$result = $client->__soapCall('sfexpressService', array("xml" => $xml, "verifyCode"=> $verifyCode));

return $result; //返回xml格式
}

public function array2xml($var, $type = 'root', $tag = '') {
$ret = '';
if (!is_int($type)) {
if ($tag)
return $this->array2xml(array($tag => $var), 0, $type); else {
$tag .= $type;
$type = 0;
}
}
$level = $type;
$indent = str_repeat("\t", $level);
if (!is_array($var)) {
$ret .= $indent . '<' . $tag;
$var = strval($var);
if ($var == '') {
$ret .= ' />';
} else if (!preg_match('/[^0-9a-zA-Z@\._:\/-]/', $var)) {
$ret .= '>' . $var . '</' . $tag . '>';
} else {
$ret .= "><![CDATA[{$var}]]></{$tag}>";
}
$ret .= "\n";
} else if (!(is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) && !empty($var)) {
foreach ($var as $tmp)
$ret .= $this->array2xml($tmp, $level, $tag);
} else {
$ret .= $indent . '<' . $tag;
if ($level == 0)
$ret .= '';
if (isset($var['@attributes'])) {
foreach ($var['@attributes'] as $k => $v) {
if (!is_array($v)) {
$ret .= sprintf(' %s="%s"', $k, $v);
}
}
unset($var['@attributes']);
}
$ret .= ">\n";
foreach ($var as $key => $val) {
$ret .= $this->array2xml($val, $level + 1, $key);
}
$ret .= "{$indent}</{$tag}>\n";
}
return $ret;
}

}

这个方法只是个sf获取货运号的对象类,里面的逻辑可以大致看看结构。
3. 开始多线程操作,注意,上面我们搞了一个多线程的执行类,我们需要通过调用的方式让他执行:

<?php
/*
根据国家和订单金额,选择货运公司,此功能是通过console跑的脚本
*/
namespace myapp\code\core\Erp\Sales\helper;
use Yii;
use backend\block\Blockbase;
use backend\models\core\Date;
use myapp\code\core\Erp\Sales\helper\Orderstatus;
use myapp\code\core\Erp\Sales\models\Salesorderitem;
use myapp\code\core\Erp\Sales\models\Salesorder;

use myapp\code\core\Erp\Sales\helper\shipping\DHL;
use myapp\code\core\Erp\Sales\helper\shipping\Sf;
use myapp\code\core\Erp\Sales\helper\shipping\PXdsf;
use myapp\code\core\Erp\Sales\helper\shipping\Bilishi;
use myapp\code\core\Erp\Sales\helper\shipping\Eyoubao;
use myapp\code\core\XPublic\Shipping\TrackingNo;
class Shippingpthreads
{
# 顺丰平邮
const SF_PINGYOU_A2 = "SF_PINGYOU_A2";
# 顺丰国际
const SF_GUOJI_A1 = "SF_GUOJI_A1";
# 顺丰澳洲a6
const SF_PINGYOU_A6 = "SF_PINGYOU_A6";
# DHL
const DHL = "DHL";

# ****************XXXXX---->4PX 中国邮政EMS
# 已经更改为夏普 中国邮政EMS
const PX_EMS_C1 = "4PX_EMS_C1";
# ****************XXXXX---->4PX 新加坡邮政
# 已经更改为夏普 新加坡邮政
const PX_XJP_B1 = "4PX_XJP_B1";

# 比利时邮政
const BILISHI = "BILISHI";
# E邮宝
const E_YOUBAO = "E_YOUBAO";

public static function getShippingCompanyArray(){
return [
self::SF_PINGYOU_A2 => '顺丰平邮-A2',
self::SF_GUOJI_A1 => '顺丰国际-A1',
self::SF_PINGYOU_A6 => '顺丰平邮-A6',
self::DHL => 'DHL',
self::PX_EMS_C1 => '4PX-中国邮政EMS',
self::PX_XJP_B1 => '4PX-新加坡邮政',
self::BILISHI => '比利时邮政',
self::E_YOUBAO => 'E邮宝',
];
}
# 得到货运追踪号失败的最大次数。
const GET_TRACKING_NUMBER_MAX_FAIL_COUNT = 5;

# 开始货运号追踪,并更新
public static function getOrdersTrackNumber(){

$orders = self::getOrders();
#$orders = self::getDOrders();
//var_dump($orders);exit;
$thread_array = [];
//var_dump($orders);exit;
echo "Get TrackNumber By Pthreads begin ...\n";
# 多线程获取订单货运号 Pthreads
foreach($orders as $order){
$increment_id = $order['increment_id'];
$thread_array[$increment_id] = new TrackOrderPthreads($order);
$thread_array[$increment_id]->start();
}
$track_arr = [];

foreach($thread_array as $increment_id=>$thread_ob){
while($thread_array[$increment_id]->isRunning()){
#失败的沉睡3秒。
sleep(3);
$thread_array[$increment_id]->kill();
break;
}
if($thread_array[$increment_id]->join()){
$track_arr[] = $thread_array[$increment_id]->data;
}

}
echo "Get TrackNumber By Pthreads end ...\n";
foreach($track_arr as $track){
if($track){

var_dump($track);
echo "\n";
$content = $track['content'];

$tracking_number = $track['trackingNumber'];
$mailno = $track['mailno'];
$orderNo = $track['orderNo'];

$content = $track['content'];
$ack = $track['ack'];
//echo $orderNo.'-'.$tracking_number."<br/>";
//$tracking_number_status = $track['tracking_number_status'];

# 重新获取
$order = Salesorder::find()->where(['increment_id'=>$orderNo])
->one();
if( $ack == 'success' && $order && $tracking_number){
if($order->erp_global_status == Orderstatus::ORDER_GLOBAL_STATUS_GET_FREIGHT_COMPLETE){

//echo "##";
$increment_id = $order['increment_id'];
$one_order = Salesorder::find()->where(" increment_id != '".$increment_id."' and tracking_number = '".$tracking_number."' ")
->one();
# 如果这个货运号,在其他订单中存在,则这个货运号不允许被保存。
if($one_order['increment_id']){
echo "tracking_number is alreay exit\n";
$order->get_tracking_number_status = 2;
$order->get_tracking_number_return_code = 'tracking_number is alreay exit,can not save to this order';
$order->get_tracking_number_datetime = Date::getCurrentDateTime();
$order->erp_global_status = Orderstatus::ORDER_GLOBAL_STATUS_GET_FREIGHT_COMPLETE;
//$order->erp_order_get_freight_company_datetime = date::getCurrentDateTime();
$order->get_tracking_number_fail_count = $order->get_tracking_number_fail_count + 1;
$order->save();

}else{
echo "save ".$increment_id." success \n";
$order->tracking_number = $tracking_number;
$order->mail_no = $mailno;
$order->get_tracking_number_status = 1;
$order->get_tracking_number_return_code = $content;
$order->get_tracking_number_datetime = Date::getCurrentDateTime();
//$order->erp_order_get_freight_company_datetime = date::getCurrentDateTime();
$order->erp_global_status = Orderstatus::ORDER_GLOBAL_STATUS_GET_CARGO_NO_COMPLETE;
$order->save();

}
}
}else if($order){
echo "Get Track Number Ack : Fail \n";
if($order->erp_global_status == Orderstatus::ORDER_GLOBAL_STATUS_GET_FREIGHT_COMPLETE){
$order->tracking_number = $tracking_number;
$order->get_tracking_number_status = 2;
$order->get_tracking_number_return_code = $content;
$order->get_tracking_number_datetime = Date::getCurrentDateTime();
$order->erp_global_status = Orderstatus::ORDER_GLOBAL_STATUS_GET_FREIGHT_COMPLETE;
//$order->erp_order_get_freight_company_datetime = date::getCurrentDateTime();
$order->get_tracking_number_fail_count = $order->get_tracking_number_fail_count + 1;
$order->save();
}
}
}else{
echo "Return Null \n";
}
}

}

public static function getDOrders(){
$order1 = Salesorder::find()->asArray()->where(['increment_id'=>'INTOSMILEES000000678'])->one();
$order2 = Salesorder::find()->asArray()->where(['increment_id'=>'55c2c0d275e08241edaef6af'])->one();

$increment_ids = [
'SBxxxx10000000101',
'SBxxxx10000000102',
'SBxxxx10000000103',
'SBxxxx10000000104',
'SBxxxx10000000105',
'SBxxxx10000000106',
'SBxxxx10000000107',
'SBxxxx10000000108',

];

$order1 = self::getTrackOrder($order1);
$order2 = self::getTrackOrder($order2);
$re_order = [];
foreach($increment_ids as $increment_id){
$order1['increment_id'] = $increment_id;

$re_order[] = $order1;
}

$re_order[0]['shipping_company'] = 'SF_PINGYOU_A2';
$re_order[1]['shipping_company'] = 'SF_GUOJI_A1';
$re_order[2]['shipping_company'] = 'SF_PINGYOU_A6';
$re_order[3]['shipping_company'] = '4PX_EMS_C1';
$re_order[4]['shipping_company'] = '4PX_XJP_B1';
$re_order[5]['shipping_company'] = 'DHL';
$re_order[6]['shipping_company'] = 'BILISHI';
$order2['shipping_company'] = 'E_YOUBAO';
$order2['increment_id'] = 'SBxxxx10000000109';
$re_order[] = $order2;

return $re_order;
}

/*
const SF_PINGYOU_A2 = "SF_PINGYOU_A2";
# 顺丰国际
const SF_GUOJI_A1 = "SF_GUOJI_A1";
# 顺丰澳洲a6
const SF_PINGYOU_A6 = "SF_PINGYOU_A6";
# DHL
const DHL = "DHL";

# ****************XXXXX---->4PX 中国邮政EMS
# 已经更改为夏普 中国邮政EMS
const PX_EMS_C1 = "4PX_EMS_C1";
# ****************XXXXX---->4PX 新加坡邮政
# 已经更改为夏普 新加坡邮政
const PX_XJP_B1 = "4PX_XJP_B1";

# 比利时邮政
const BILISHI = "BILISHI";
# E邮宝
const E_YOUBAO = "E_YOUBAO";

*/

# 得到要处理的订单。
public static function getOrders(){

$condition = Orderstatus::ORDER_GLOBAL_STATUS_GET_FREIGHT_COMPLETE;
$where = " erp_global_status= ".$condition." AND get_tracking_number_fail_count < ".Shipping::GET_TRACKING_NUMBER_MAX_FAIL_COUNT." AND get_tracking_number_status <> 1";

$orders_model = Salesorder::find()->asArray()->where($where)
->limit(500)
;

$orders = $orders_model->all();
$track_orders = [];

foreach($orders as $order){

$order = self::getTrackOrder($order);
//$order = self::getTrackingInfo($order);
if($order['increment_id']){
$track_orders[] = $order;
}
}

return $track_orders;

/*
$count = $orders_model->count();
echo "where:".$where.'\n';
echo "count:".$count.'\n';
foreach($orders as $order){
echo "process:".$order['increment_id']." begin..\n";
$noworder = Salesorder::find()->where(['increment_id'=>$order['increment_id']])
->andWhere($where)
->one();
if($noworder['increment_id']){
Shipping::settrackingnumber($noworder);
}
echo "process:".$order['increment_id']." end..\n";
}
*/
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: