|
|
<?php
|
|
|
|
|
|
namespace app\common\shipping;
|
|
|
|
|
|
use GuzzleHttp\Client;
|
|
|
use Ecpay\Sdk\Factories\Factory;
|
|
|
use Ecpay\Sdk\Services\CheckMacValueService;
|
|
|
|
|
|
use app\common\shipping\Ishipping;
|
|
|
|
|
|
use think\facade\Db;
|
|
|
use think\facade\Log;
|
|
|
|
|
|
//實作物流串接介面
|
|
|
class EcpayShipping implements Ishipping
|
|
|
{
|
|
|
|
|
|
private $api_url;
|
|
|
private $MerchantId;
|
|
|
private $HashIv;
|
|
|
private $HashKey;
|
|
|
private $SenderName;
|
|
|
private $SenderPhone;
|
|
|
|
|
|
public function __construct()
|
|
|
{
|
|
|
$shipping = Db::name('shipping')
|
|
|
->where('shipping_code', 'ecpay')
|
|
|
->find();
|
|
|
|
|
|
$config = json_decode($shipping['shipping_config'], true);
|
|
|
|
|
|
if ($shipping['is_test'] == 0) {
|
|
|
$this->api_url = 'https://logistics-stage.ecpay.com.tw';
|
|
|
$this->MerchantId = '2000933';
|
|
|
$this->HashIv = 'h1ONHk4P4yqbl5LK';
|
|
|
$this->HashKey = 'XBERn1YOvpM9nfZc';
|
|
|
$this->SenderName = isset($config['SenderName']) ? $config['SenderName'] : '測試人員';
|
|
|
$this->SenderPhone = isset($config['SenderPhone']) ? $config['SenderPhone'] : '0900000001';
|
|
|
} else {
|
|
|
if (empty($config['MerchantId']) || empty($config['HashIv']) || empty($config['HashKey'])) {
|
|
|
throw new \Exception('請先設定綠界物流參數');
|
|
|
}
|
|
|
$this->api_url = 'https://logistics.ecpay.com.tw';
|
|
|
$this->MerchantId = $config['MerchantId'];
|
|
|
$this->HashIv = $config['HashIv'];
|
|
|
$this->HashKey = $config['HashKey'];
|
|
|
$this->SenderName = isset($config['SenderName']) ? $config['SenderName'] : getConfigValue('service_company');
|
|
|
$this->SenderPhone = isset($config['SenderPhone']) ? $config['SenderPhone'] : getConfigValue('service_phone');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public function request($order)
|
|
|
{
|
|
|
$subType['1'] = 'UNIMARTC2C';
|
|
|
$subType['2'] = 'FAMIC2C';
|
|
|
$subType['3'] = 'HILIFEC2C';
|
|
|
$subType['4'] = 'OKMARTC2C';
|
|
|
|
|
|
$goods_list = '';
|
|
|
foreach ($order['goods_list'] as $goods) {
|
|
|
$goods_list .= $goods['goods_name'] . "#";
|
|
|
//如果$goods_list結尾是#,則去掉
|
|
|
if (substr($goods_list, -1) == '#') {
|
|
|
$goods_list = substr($goods_list, 0, -1);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
$logistics = json_decode($order['address'], true);
|
|
|
|
|
|
|
|
|
// 綠界物流串接
|
|
|
$factory = new Factory([
|
|
|
'hashKey' => $this->HashKey,
|
|
|
'hashIv' => $this->HashIv,
|
|
|
'hashMethod' => 'md5',
|
|
|
]);
|
|
|
|
|
|
$ecService = $factory->create('PostWithCmvStrResponseService');
|
|
|
|
|
|
$shipping_data = [
|
|
|
'MerchantID' => $this->MerchantId,
|
|
|
'LogisticsType' => 'CVS',
|
|
|
'MerchantTradeNo' => $order['order_sn'],
|
|
|
'MerchantTradeDate' => date('Y/m/d H:i:s'),
|
|
|
'LogisticsSubType' => $subType[$logistics['type']],
|
|
|
'GoodsAmount' => $order['order_amount'],
|
|
|
'CollectionAmount' => $order['order_amount'],
|
|
|
'IsCollection' => $order['pay_id'] == 0 ? 'Y' : 'N',
|
|
|
'GoodsName' => $goods_list,
|
|
|
'SenderName' => $this->SenderName,
|
|
|
'SenderPhone' => $this->SenderPhone,
|
|
|
'SenderCellPhone' => $this->SenderPhone,
|
|
|
'ReceiverName' => $order['consignee'],
|
|
|
// 'ReceiverPhone' => $user_info['mobile_phone'],
|
|
|
'ReceiverCellPhone' => $order['mobile'],
|
|
|
'ReceiverStoreID' => $logistics['store_id'],
|
|
|
'ServerReplyURL' => getUrl() . '/appapi/v1/shipping/response/shippingcode/ecpay/',
|
|
|
];
|
|
|
|
|
|
$action = $this->api_url . '/Express/Create';
|
|
|
|
|
|
$rtn = $ecService->post($shipping_data, $action);
|
|
|
$rtn = explode("|", $rtn['body']);
|
|
|
|
|
|
if ($rtn[0] === '1') {
|
|
|
parse_str($rtn[1], $data);
|
|
|
//更新訂單資料
|
|
|
try {
|
|
|
Db::name('order_info')
|
|
|
->where('order_sn', $order['order_sn'])
|
|
|
->update([
|
|
|
'shipping_status' => 3,
|
|
|
'shipping_token' => $data['AllPayLogisticsID'],
|
|
|
'shipping_data' => json_encode($data)
|
|
|
]);
|
|
|
|
|
|
// $order = Db::name('order_info')
|
|
|
// ->where('order_sn', $order['order_sn'])
|
|
|
// ->find();
|
|
|
|
|
|
//更新訂單操縱紀錄
|
|
|
// $order_action = [
|
|
|
// 'order_id' => $order['order_id'],
|
|
|
// 'action_user' => '綠界科技',
|
|
|
// 'order_status' => $order['order_status'],
|
|
|
// 'shipping_status' => $order['shipping_status'],
|
|
|
// 'pay_status' => $order['pay_status'],
|
|
|
// 'action_note' => '綠界物流:' . $data['LogisticsSubType'] . ',' . $data['RtnMsg'],
|
|
|
// 'log_time' => strtotime($data['UpdateStatusDate'])
|
|
|
// ];
|
|
|
// Db::name('order_action')->insert($order_action);
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
return ['code' => 500, 'msg' => $e->getMessage()];
|
|
|
}
|
|
|
|
|
|
return ['code' => 200, 'msg' => '更新成功'];
|
|
|
} else {
|
|
|
return ['code' => 500, 'msg' => $rtn[1]];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public function response($data)
|
|
|
{
|
|
|
Log::write('綠界物流回傳:' . json_encode($data));
|
|
|
//判斷是否為綠界回傳資料
|
|
|
if (!isset($data['AllPayLogisticsID'])) {
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
//TODO: 檢查碼驗證
|
|
|
//建立checkMacValueService物件
|
|
|
// $checkMacValueService = new CheckMacValueService($this->HashKey, $this->HashIv, 'md5');
|
|
|
//檢查碼驗證
|
|
|
// $checkMacValue = $checkMacValueService->generate($data);
|
|
|
|
|
|
// if($checkMacValue != $data['CheckMacValue']){
|
|
|
// return FALSE;
|
|
|
// }
|
|
|
|
|
|
$code = 201;
|
|
|
$message = '';
|
|
|
|
|
|
$order = Db::name('order_info')->where('order_sn', $data['MerchantTradeNo'])->find();
|
|
|
|
|
|
switch ($data['LogisticsSubType']) {
|
|
|
case 'UNIMARTC2C':
|
|
|
switch ($data['RtnCode']) {
|
|
|
case '300':
|
|
|
$update_data = [
|
|
|
'shipping_status' => 3,
|
|
|
];
|
|
|
break;
|
|
|
case '2073':
|
|
|
//物流已達取件門市,訂單完成
|
|
|
$update_data = [
|
|
|
'shipping_status' => 7,
|
|
|
];
|
|
|
break;
|
|
|
case '2067':
|
|
|
//物流已領取,訂單完成
|
|
|
$update_data = [
|
|
|
'shipping_status' => 2,
|
|
|
'order_status' => 7,
|
|
|
'pay_status' => 2,
|
|
|
];
|
|
|
$code = 200;
|
|
|
break;
|
|
|
case '2074':
|
|
|
//物流未領,訂單取消
|
|
|
$update_data = [
|
|
|
'shipping_status' => 4,
|
|
|
'order_status' => 6,
|
|
|
'pay_status' => 0,
|
|
|
];
|
|
|
|
|
|
//判斷是否為SlashCard商品,並且為貨到付款
|
|
|
$order = Db::name('order_info')->where('order_sn', $data['MerchantTradeNo'])->find();
|
|
|
$is_main = Db::name('order_goods')
|
|
|
->where('order_id', $order['order_id'])
|
|
|
->where('goods_id', 1)
|
|
|
->find();
|
|
|
|
|
|
if ($is_main && $order['pay_id'] == 0) {
|
|
|
//將slashcard訂單取消
|
|
|
$rtn = \app\service\Card::cancelUser([
|
|
|
'order_sn' => $order['order_sn'],
|
|
|
'user_id' => Db::name('users')->where('user_id', $order['user_id'])->value('sso_user_id'),
|
|
|
]);
|
|
|
|
|
|
if ($rtn['code'] != 200) {
|
|
|
// 扣除點數失敗
|
|
|
}
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
default:
|
|
|
$update_data = [
|
|
|
'shipping_status' => 1,
|
|
|
];
|
|
|
break;
|
|
|
}
|
|
|
break;
|
|
|
case 'FAMIC2C':
|
|
|
switch ($data['RtnCode']) {
|
|
|
case '3032':
|
|
|
//至超商寄貨
|
|
|
$update_data = [
|
|
|
'shipping_status' => 5,
|
|
|
'order_status' => $order['order_status'],
|
|
|
'pay_status' => $order['pay_status'],
|
|
|
];
|
|
|
break;
|
|
|
case '3018':
|
|
|
//物流已達取件門市,訂單完成
|
|
|
$update_data = [
|
|
|
'shipping_status' => 7,
|
|
|
];
|
|
|
break;
|
|
|
|
|
|
case '3022':
|
|
|
$update_data = [
|
|
|
'shipping_status' => 2,
|
|
|
'order_status' => 7,
|
|
|
'pay_status' => 2,
|
|
|
];
|
|
|
$code = 200;
|
|
|
break;
|
|
|
case '3020':
|
|
|
//物流未領,訂單取消
|
|
|
$update_data = [
|
|
|
'shipping_status' => 4,
|
|
|
'order_status' => 6,
|
|
|
'pay_status' => 0,
|
|
|
];
|
|
|
//判斷是否為SlashCard商品,並且為貨到付款
|
|
|
$order = Db::name('order_info')->where('order_sn', $data['MerchantTradeNo'])->find();
|
|
|
$is_main = Db::name('order_goods')
|
|
|
->where('order_id', $order['order_id'])
|
|
|
->where('goods_id', 1)
|
|
|
->find();
|
|
|
|
|
|
if ($is_main && $order['pay_id'] == 0) {
|
|
|
//將slashcard訂單取消
|
|
|
$rtn = \app\service\Card::cancelUser([
|
|
|
'order_sn' => $order['order_sn'],
|
|
|
'user_id' => Db::name('users')->where('user_id', $order['user_id'])->value('sso_user_id'),
|
|
|
]);
|
|
|
|
|
|
if ($rtn['code'] != 200) {
|
|
|
// 扣除點數失敗
|
|
|
}
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
default:
|
|
|
$update_data = [
|
|
|
'shipping_status' => 1,
|
|
|
'order_status' => $order['order_status'],
|
|
|
'pay_status' => $order['pay_status'],
|
|
|
];
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
break;
|
|
|
case 'HILIFEC2C':
|
|
|
switch ($data['RtnCode']) {
|
|
|
case '2001':
|
|
|
//物流單成立
|
|
|
$update_data = [
|
|
|
'shipping_status' => 3,
|
|
|
];
|
|
|
break;
|
|
|
case '3018':
|
|
|
case '2063':
|
|
|
//物流已達取件門市,訂單完成
|
|
|
$update_data = [
|
|
|
'shipping_status' => 7,
|
|
|
];
|
|
|
break;
|
|
|
|
|
|
case '3022':
|
|
|
case '2067':
|
|
|
$update_data = [
|
|
|
'shipping_status' => 2,
|
|
|
'order_status' => 7,
|
|
|
'pay_status' => 2,
|
|
|
];
|
|
|
$code = 200;
|
|
|
break;
|
|
|
case '3020':
|
|
|
case '2074':
|
|
|
//物流未領,訂單取消
|
|
|
$update_data = [
|
|
|
'shipping_status' => 4,
|
|
|
'order_status' => 6,
|
|
|
'pay_status' => 0,
|
|
|
];
|
|
|
//判斷是否為SlashCard商品,並且為貨到付款
|
|
|
$order = Db::name('order_info')->where('order_sn', $data['MerchantTradeNo'])->find();
|
|
|
$is_main = Db::name('order_goods')
|
|
|
->where('order_id', $order['order_id'])
|
|
|
->where('goods_id', 1)
|
|
|
->find();
|
|
|
|
|
|
if ($is_main && $order['pay_id'] == 0) {
|
|
|
//將slashcard訂單取消
|
|
|
$rtn = \app\service\Card::cancelUser([
|
|
|
'order_sn' => $order['order_sn'],
|
|
|
'user_id' => Db::name('users')->where('user_id', $order['user_id'])->value('sso_user_id'),
|
|
|
]);
|
|
|
|
|
|
if ($rtn['code'] != 200) {
|
|
|
// 扣除點數失敗
|
|
|
}
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
$update_data = [
|
|
|
'shipping_status' => 1,
|
|
|
'order_status' => $order['order_status'],
|
|
|
'pay_status' => $order['pay_status'],
|
|
|
];
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
break;
|
|
|
case 'OKMARTC2C':
|
|
|
switch ($data['RtnCode']) {
|
|
|
case '300':
|
|
|
$update_data = [
|
|
|
'shipping_status' => 3,
|
|
|
];
|
|
|
break;
|
|
|
case '2073':
|
|
|
//物流已達取件門市,訂單完成
|
|
|
$update_data = [
|
|
|
'shipping_status' => 7,
|
|
|
];
|
|
|
break;
|
|
|
case '3022':
|
|
|
$update_data = [
|
|
|
'shipping_status' => 2,
|
|
|
'order_status' => 7,
|
|
|
'pay_status' => 2,
|
|
|
];
|
|
|
$code = 200;
|
|
|
break;
|
|
|
case '3032':
|
|
|
//至超商寄貨
|
|
|
$update_data = [
|
|
|
'shipping_status' => 1, //已發貨
|
|
|
'order_status' => $order['order_status'],
|
|
|
'pay_status' => $order['pay_status'],
|
|
|
];
|
|
|
break;
|
|
|
case '2074':
|
|
|
//物流未領,訂單取消
|
|
|
$update_data = [
|
|
|
'shipping_status' => 4,
|
|
|
'order_status' => 6,
|
|
|
'pay_status' => 0,
|
|
|
];
|
|
|
//判斷是否為SlashCard商品,並且為貨到付款
|
|
|
$order = Db::name('order_info')->where('order_sn', $data['MerchantTradeNo'])->find();
|
|
|
$is_main = Db::name('order_goods')
|
|
|
->where('order_id', $order['order_id'])
|
|
|
->where('goods_id', 1)
|
|
|
->find();
|
|
|
|
|
|
if ($is_main && $order['pay_id'] == 0) {
|
|
|
//將slashcard訂單取消
|
|
|
$rtn = \app\service\Card::cancelUser([
|
|
|
'order_sn' => $order['order_sn'],
|
|
|
'user_id' => Db::name('users')->where('user_id', $order['user_id'])->value('sso_user_id'),
|
|
|
]);
|
|
|
|
|
|
if ($rtn['code'] != 200) {
|
|
|
// 扣除點數失敗
|
|
|
}
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
default:
|
|
|
$update_data = [
|
|
|
'shipping_status' => 1,
|
|
|
'order_status' => $order['order_status'],
|
|
|
'pay_status' => $order['pay_status'],
|
|
|
];
|
|
|
break;
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
|
$code = 500;
|
|
|
break;
|
|
|
}
|
|
|
try {
|
|
|
//新增物流紀錄到order_shipping
|
|
|
$shipping_data = [
|
|
|
'order_id' => Db::name('order_info')->where('order_sn', $data['MerchantTradeNo'])->value('order_id'),
|
|
|
'code' => $data['RtnCode'],
|
|
|
'note' => $data['RtnMsg'],
|
|
|
'create_time' => strtotime($data['UpdateStatusDate']),
|
|
|
];
|
|
|
|
|
|
Db::name('order_shipping')->insert($shipping_data);
|
|
|
|
|
|
//更新訂單資料
|
|
|
if (isset($update_data)) {
|
|
|
Db::name('order_info')
|
|
|
->where('order_sn', $data['MerchantTradeNo'])
|
|
|
->update($update_data);
|
|
|
}
|
|
|
|
|
|
//更新訂單操作記錄
|
|
|
$order_info = Db::name('order_info')
|
|
|
->where('order_sn', $data['MerchantTradeNo'])
|
|
|
->find();
|
|
|
|
|
|
Db::name('order_action')
|
|
|
->insert(
|
|
|
[
|
|
|
'order_id' => $order_info['order_id'],
|
|
|
'action_user' => '綠界科技',
|
|
|
'order_status' => $order_info['order_status'],
|
|
|
'shipping_status' => $order_info['shipping_status'],
|
|
|
'pay_status' => $order_info['pay_status'],
|
|
|
'action_note' => '綠界物流:' . $data['LogisticsSubType'] . ',' . $data['RtnMsg'],
|
|
|
'log_time' => strtotime($data['UpdateStatusDate'])
|
|
|
]
|
|
|
);
|
|
|
} catch (\Exception $e) {
|
|
|
$code = 500;
|
|
|
$message = $e->getMessage();
|
|
|
}
|
|
|
|
|
|
$rtn = [
|
|
|
'code' => $code,
|
|
|
'shippingcode' => 'ecpay',
|
|
|
'msg' => $message,
|
|
|
'order_sn' => $data['MerchantTradeNo'],
|
|
|
];
|
|
|
|
|
|
return $rtn;
|
|
|
}
|
|
|
|
|
|
public function map($params)
|
|
|
{
|
|
|
// 綠界物流地圖串接
|
|
|
$factory = new Factory([
|
|
|
'hashKey' => $this->HashKey,
|
|
|
'hashIv' => $this->HashIv,
|
|
|
'hashMethod' => 'md5',
|
|
|
]);
|
|
|
|
|
|
$formService = $factory->create('ReturnSubmitFormWithCmvService');
|
|
|
|
|
|
$input = [
|
|
|
'MerchantID' => $this->MerchantId,
|
|
|
'LogisticsType' => 'CVS',
|
|
|
'ServerReplyURL' => getUrl() . '/appapi/v1/shipping/mapresponse/shippingcode/ecpay/',
|
|
|
];
|
|
|
|
|
|
$input = array_merge($input, $params);
|
|
|
$action = $this->api_url . '/Express/map';
|
|
|
return $formService->generate($input, $action);
|
|
|
}
|
|
|
|
|
|
public function mapResponse($data)
|
|
|
{
|
|
|
//將LogisticsSubType轉換成數字
|
|
|
switch ($data['LogisticsSubType']) {
|
|
|
case 'UNIMARTC2C':
|
|
|
$data['LogisticsSubType'] = 1;
|
|
|
break;
|
|
|
case 'FAMIC2C':
|
|
|
$data['LogisticsSubType'] = 2;
|
|
|
break;
|
|
|
case 'HILIFEC2C':
|
|
|
$data['LogisticsSubType'] = 3;
|
|
|
break;
|
|
|
case 'OKMARTC2C':
|
|
|
$data['LogisticsSubType'] = 4;
|
|
|
break;
|
|
|
default:
|
|
|
return FALSE;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
$iData = [
|
|
|
'user_id' => getIdBySsoId($data['ExtraData']),
|
|
|
'type' => $data['LogisticsSubType'],
|
|
|
'store_id' => $data['CVSStoreID'],
|
|
|
'store_name' => $data['CVSStoreName'],
|
|
|
'store_address' => $data['CVSAddress'],
|
|
|
'store_tel' => $data['CVSTelephone'],
|
|
|
'is_default' => 1,
|
|
|
];
|
|
|
|
|
|
//將$data寫入user_cvs資料庫
|
|
|
|
|
|
$is_exist = Db::name('user_cvs')
|
|
|
->where('store_id', $data['CVSStoreID'])
|
|
|
->where('user_id', getIdBySsoId($data['ExtraData']))
|
|
|
->count();
|
|
|
|
|
|
try {
|
|
|
//將所有的is_default設為0
|
|
|
Db::name('user_cvs')
|
|
|
->where('user_id', getIdBySsoId($data['ExtraData']))
|
|
|
->update(['is_default' => 0]);
|
|
|
|
|
|
if (!$is_exist) {
|
|
|
Db::name('user_cvs')->insert($iData);
|
|
|
} else {
|
|
|
//將該筆資料的is_default設為1
|
|
|
Db::name('user_cvs')
|
|
|
->where('user_id', getIdBySsoId($data['ExtraData']))
|
|
|
->where('store_id', $data['CVSStoreID'])
|
|
|
->update(['is_default' => 1]);
|
|
|
}
|
|
|
} catch (\Exception $e) {
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
// $result['redirect_url'] = 'http://localhost:5173/m/order/shipping?is_return=1';
|
|
|
$result['redirect_url'] = getUrl() . '/m/order/shipping?is_return=1';
|
|
|
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
public function printLabel($params)
|
|
|
{
|
|
|
|
|
|
$factory = new Factory([
|
|
|
'hashKey' => $this->HashKey,
|
|
|
'hashIv' => $this->HashIv,
|
|
|
'hashMethod' => 'md5',
|
|
|
]);
|
|
|
|
|
|
$formService = $factory->create('AutoSubmitFormWithCmvService');
|
|
|
|
|
|
$input = [
|
|
|
'MerchantID' => $this->MerchantId,
|
|
|
'PlatformID' => '',
|
|
|
];
|
|
|
|
|
|
$input = array_merge($input, $params);
|
|
|
|
|
|
switch ($params['type']) {
|
|
|
case 'UNIMARTC2C':
|
|
|
$action = $this->api_url . '/Express/PrintUniMartC2COrderInfo';
|
|
|
break;
|
|
|
case 'FAMIC2C':
|
|
|
$action = $this->api_url . '/Express/PrintFAMIC2COrderInfo';
|
|
|
break;
|
|
|
case 'HILIFEC2C':
|
|
|
$action = $this->api_url . '/Express/PrintHiLifeC2COrderInfo';
|
|
|
break;
|
|
|
case 'OKMARTC2C':
|
|
|
$action = $this->api_url . '/Express/PrintOKMARTC2COrderInfo';
|
|
|
break;
|
|
|
}
|
|
|
return $formService->generate($input, $action);
|
|
|
}
|
|
|
}
|