diff --git a/packages/bydauto/migrations/2024_11_13_160651_create_bydauto_tables.php b/packages/bydauto/migrations/2024_11_13_160651_create_bydauto_tables.php
index 5fe2045..780a515 100644
--- a/packages/bydauto/migrations/2024_11_13_160651_create_bydauto_tables.php
+++ b/packages/bydauto/migrations/2024_11_13_160651_create_bydauto_tables.php
@@ -4,8 +4,7 @@
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
-return new class extends Migration
-{
+return new class extends Migration {
public function up(): void
{
Schema::create('bydauto_contact', function (Blueprint $table) {
diff --git a/packages/bydauto/routes/api.php b/packages/bydauto/routes/api.php
index 15252be..906101a 100644
--- a/packages/bydauto/routes/api.php
+++ b/packages/bydauto/routes/api.php
@@ -11,4 +11,7 @@
Route::get('province', [BYDAutoController::class, 'province']);
Route::get('city', [BYDAutoController::class, 'city']);
Route::post('testdrive', [BYDAutoController::class, 'testdrive']);
+ Route::post('isaas', [BYDAutoController::class, 'isaas']);
+ Route::post('cluepackage', [BYDAutoController::class, 'cluepackage']);
+ Route::post('notice', [BYDAutoController::class, 'notice']);
});
diff --git a/packages/bydauto/src/Commands/CheryTransferCommand.php b/packages/bydauto/src/Commands/CheryTransferCommand.php
index d3259cb..70ddda9 100644
--- a/packages/bydauto/src/Commands/CheryTransferCommand.php
+++ b/packages/bydauto/src/Commands/CheryTransferCommand.php
@@ -75,6 +75,6 @@ public function action_dispatch_by_mobile()
protected function showTable($items)
{
$columns = ['id', 'status', 'name', 'mobile'];
- $this->table($columns, $items->map(fn($item) => $item->only($columns)));
+ $this->table($columns, $items->map(fn ($item) => $item->only($columns)));
}
}
diff --git a/packages/bydauto/src/Commands/GeocodingCommand.php b/packages/bydauto/src/Commands/GeocodingCommand.php
index f0622e1..031d697 100644
--- a/packages/bydauto/src/Commands/GeocodingCommand.php
+++ b/packages/bydauto/src/Commands/GeocodingCommand.php
@@ -91,7 +91,7 @@ public function xlsx($chunk, $index)
$sheet->setCellValue('J' . $sn, '09:00-18:00');
$sheet->setCellValue('K' . $sn, '');
- $vehicles = $dealer->vehicles->map(fn($v) => $v->extra_code)->join(',');
+ $vehicles = $dealer->vehicles->map(fn ($v) => $v->extra_code)->join(',');
$vehicles = trim($vehicles, ',');
$sheet->setCellValue('L' . $sn, $vehicles);
@@ -159,14 +159,14 @@ public function action_csv()
{
$items = Dealer::query()->orderBy('id')->get();
$chunks = $items->chunk(200);
- $chunks->each(fn($chunk, $index) => $this->xlsx($chunk, $index));
+ $chunks->each(fn ($chunk, $index) => $this->xlsx($chunk, $index));
}
public function action_xlsx()
{
$items = Dealer::query()->orderBy('id')->get();
$chunks = $items->chunk(200);
- $chunks->each(fn($chunk, $index) => $this->xlsx($chunk, $index));
+ $chunks->each(fn ($chunk, $index) => $this->xlsx($chunk, $index));
}
public function action_dump()
@@ -179,7 +179,7 @@ public function action_dump()
public function action_show()
{
$items = Dealer::query()->take(4)->get();
- $this->table(['CODE', '经销商名称', '在售车型'], $items->map(fn(Dealer $d) => [$d->erp, $d->alias, $d->vehicles->map(fn($v) => $v->spec_id)->join(',')]));
+ $this->table(['CODE', '经销商名称', '在售车型'], $items->map(fn (Dealer $d) => [$d->erp, $d->alias, $d->vehicles->map(fn ($v) => $v->spec_id)->join(',')]));
}
public function action_fix()
diff --git a/packages/bydauto/src/Controllers/BYDAutoController.php b/packages/bydauto/src/Controllers/BYDAutoController.php
index e79650e..c50c63e 100644
--- a/packages/bydauto/src/Controllers/BYDAutoController.php
+++ b/packages/bydauto/src/Controllers/BYDAutoController.php
@@ -3,8 +3,8 @@
namespace BYDAuto\Controllers;
use BYDAuto\Actions\TestdriveCreateAction;
-use BYDAuto\Models\Dealer;
-use BYDAuto\Models\Vehicle;
+use BYDAuto\Foundation\Encryption;
+use BYDAuto\Models\Testdrive;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
@@ -29,41 +29,71 @@ public function testdrive(Request $request)
return response()->json(['code' => 0, 'message' => '提交成功', 'request_id' => $requestId]);
}
- public function vehicle(Request $request)
+ // 行业云留资SPI接口 实现
+ // https://vm1112app.arsk.net/pkg/bydauto/isaas
+ public function isaas(Request $request)
{
- $items = Vehicle::cachedItems();
- return response()->json($items);
- }
+ $input = $request->all();
+ info('===== bydautoController::isaas', $input);
- public function province(Request $request)
- {
- $vehicle = Vehicle::query()->firstWhere('name', $request->vehicle);
- $dealers = $vehicle->dealers;
- $province = $dealers->groupBy('province')->keys();
- $data = $province->map(fn($item) => ['name' => $item]);
- return response()->json($data);
- }
+ $biz_content = $input['biz_content'] ?? '';
+ throw_if(empty($biz_content), ValidationException::withMessages(['biz_content' => 'missing biz_content']));
- public function city(Request $request)
- {
- $vehicle = Vehicle::query()->firstWhere('name', $request->vehicle);
- if (!$vehicle) {
- throw ValidationException::withMessages(['vehicle' => '车型不存在']);
+ $key = 'f4LNNKURSfT4/p5ne4xXdW45vcUahojQDEb+dejxUq8=';
+ try {
+ $iv = str_repeat("\0", 16);
+ $data = openssl_decrypt(base64_decode($biz_content), 'AES-256-CBC', base64_decode($key), OPENSSL_RAW_DATA, $iv);
+ $data = json_decode($data, true);
+ Testdrive::isaas($data);
+ } catch (\Throwable $th) {
+ info('===== [biz_content decrypt fail]', [$th->getMessage()]);
}
- $dealers = $vehicle->dealers;
- $city = $dealers->where('province', $request->province)->groupBy('city')->keys();
- $data = $city->map(fn($item) => ['name' => $item]);
- return response()->json($data);
+ // 留咨成功 success 留咨失败 failed 重复留咨 duplicate submit 系统异常 system error
+ $response = ['msg' => 'success', 'code' => '10000'];
+ $output['response'] = json_encode($response);
+ $output['sign'] = $this->sign($response);
+ return response()->json($output);
}
- public function dealer(Request $request)
+ // 实现官方标准API 专享产品-灯火平台广告投放
+ // 提供给特定广告代理商(例如 天猫),为广告主提供广告投放服务
+ // https://vm1112app.arsk.net/pkg/bydauto/cluepackage
+ // 官方定义的标准API 行业线索数据推送
+ public function cluepackage(Request $request)
{
- $vehicle = Vehicle::query()->firstWhere('name', $request->vehicle);
- if (!$vehicle) {
- throw ValidationException::withMessages(['vehicle' => '车型不存在']);
- }
- $dealer = Dealer::query()->where('province', $request->province)->where('city', $request->city)->get();
- $data = $dealer->map(fn($item) => ['name' => $item->name, 'address' => $item->address, 'erp' => $item->erp]);
- return response()->json($data);
+ Testdrive::cluepackage($request->all());
+ return response()->json(['response' => ['code' => '10000', 'msg' => 'Success']]);
+ }
+
+ // 支付宝支付通知(应用网关)https://vm1112app.arsk.net/pkg/bydauto/notice
+ // 用于接收支付宝异步通知消息(例如From平台消息等),需要传入http(s)公网可访问的网页地址。选填,若不设置,则无法接收相应的异步通知消息
+ public function notice(Request $request)
+ {
+ $input = $request->all();
+ info('===== notice', $input);
+ return response('');
+ }
+
+ protected function sign($input)
+ {
+ $pubkey = file_get_contents(storage_path('app/pkg/chery-crm/isaas/app_pub_RSA2048.txt'));
+ $pubkey = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($pubkey, 64, "\n", true) . "\n-----END PUBLIC KEY-----";
+
+ $privkey = file_get_contents(storage_path('app/pkg/chery-crm/isaas/app_priv_RSA2048.txt'));
+ $privkey = "-----BEGIN PRIVATE-----\n" . wordwrap($privkey, 64, "\n", true) . "\n-----END PRIVATE-----";
+
+ $encryption = new Encryption($pubkey, $privkey);
+
+ $key = 'f4LNNKURSfT4/p5ne4xXdW45vcUahojQDEb+dejxUq8=';
+ ksort($input);
+ $input = json_encode($input, JSON_UNESCAPED_UNICODE);
+ $secretText = $this->encrypt($input, $key);
+ return $encryption->encrypt($secretText);
+ }
+
+ protected function encrypt($input, $key)
+ {
+ $iv = str_repeat("\0", 16);
+ return base64_encode(openssl_encrypt($input, 'AES-256-CBC', base64_decode($key), OPENSSL_RAW_DATA, $iv));
}
}
diff --git a/packages/bydauto/src/Models/Activity.php b/packages/bydauto/src/Models/Activity.php
index 8b6103e..8242025 100644
--- a/packages/bydauto/src/Models/Activity.php
+++ b/packages/bydauto/src/Models/Activity.php
@@ -5,7 +5,7 @@
use Illuminate\Database\Eloquent\Model;
/**
- * Activity
+ * Activity.
*
* @property int id
* @property string name
@@ -16,7 +16,10 @@
class Activity extends Model
{
public $timestamps = false;
+
protected $table = 'bydauto_activity';
+
protected $fillable = ['name', 'content', 'related_id', 'related_type'];
+
protected $casts = ['content' => 'json'];
}
diff --git a/packages/bydauto/src/Models/Contact.php b/packages/bydauto/src/Models/Contact.php
index 8ac4c66..c6bb70b 100644
--- a/packages/bydauto/src/Models/Contact.php
+++ b/packages/bydauto/src/Models/Contact.php
@@ -9,10 +9,15 @@ class Contact extends Model
{
use Notifiable;
- const STATUS_PUBLISHED = 'published';
- const STATUS_DRAFT = 'draft';
+ public const STATUS_PUBLISHED = 'published';
+
+ public const STATUS_DRAFT = 'draft';
+
public const CREATED_AT = 'date_created';
+
public const UPDATED_AT = 'date_updated';
+
protected $table = 'bydauto_contact';
+
protected $fillable = ['remark', 'email', 'status'];
}
diff --git a/packages/bydauto/src/Models/Dealer.php b/packages/bydauto/src/Models/Dealer.php
index 57def0d..a878071 100644
--- a/packages/bydauto/src/Models/Dealer.php
+++ b/packages/bydauto/src/Models/Dealer.php
@@ -37,18 +37,18 @@ public function vehicles()
public static function cachedItems()
{
- return Cache::remember('BYDAuto:dealers', 120, fn() => static::query()->get());
+ return Cache::remember('BYDAuto:dealers', 120, fn () => static::query()->get());
}
public static function findByAlias($alias)
{
$items = self::cachedItems();
- return $items->first(fn($d) => $d->alias === $alias);
+ return $items->first(fn ($d) => $d->alias === $alias);
}
public static function findByName($name)
{
$items = self::cachedItems();
- return $items->first(fn($d) => $d->name === $name);
+ return $items->first(fn ($d) => $d->name === $name);
}
}
diff --git a/packages/bydauto/src/Models/Testdrive.php b/packages/bydauto/src/Models/Testdrive.php
index 52b13ab..3d14b8e 100644
--- a/packages/bydauto/src/Models/Testdrive.php
+++ b/packages/bydauto/src/Models/Testdrive.php
@@ -2,8 +2,8 @@
namespace BYDAuto\Models;
-use Carbon\Carbon;
use BYDAuto\Observers\TestdriveObserver;
+use Carbon\Carbon;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
use Illuminate\Database\Eloquent\Model;
@@ -34,4 +34,89 @@ class Testdrive extends Model
protected $fillable = ['status', 'name', 'mobile', 'platform', 'source', 'meta', 'rawdata', 'request_id'];
protected $casts = ['meta' => 'json', 'rawdata' => 'json'];
+
+ // 行业运SPI接口数据处理
+ public static function isaas($data)
+ {
+ // {
+ // "alipayUserId": "2088002970810315",
+ // "extInfo": "",
+ // "formName": "预约试驾",
+ // "formResultBizCode": "formResult_a91a68a38acc49f1adf202ea15676909",
+ // "gmtCreate": "2024-09-04 17:38:48",
+ // "merchantAppId": "2021004170670447",
+ // "merchantPid": "2088511783986035",
+ // "propertyList": [
+ // { "key": "CID_20240904111701423264", "name": "您的姓名", "outCode": "", "value": "张伊琳" },
+ // { "key": "CID_20240904111701378536", "name": "联系电话", "outCode": "", "value": "13585623001" },
+ // { "key": "CID_20240904111701273727", "name": "意向车型", "outCode": "QR100", "value": "探索06 都市版" },
+ // { "key": "CID_20240904111701876422", "name": "选择门店", "outCode": "22486", "propertyExt": { "address": { "cityCode": "310100", "cityName": "上海城区", "provinceCode": "310000", "provinceName": "上海市" } }, "value": "上海远程汽车维修有限公司" }
+ // ],
+ // "responseClass": "com.alipay.adc.proxyopsplatform.biz.model.ecospi.response.FormDataQuerySpiResponse"
+ // }
+
+ // $externalId = $data['formResultBizCode'];
+ // $model = static::query()->where('external_id', $externalId)->first();
+ // if ($model) {
+ // info('===== isaas exists', $data);
+ // return $model;
+ // }
+ $model = new static(['source' => 'isaas', 'rawdata' => $data]);
+ foreach ($data['propertyList'] as $prop) {
+ // 手机号
+ if ($prop['name'] === '联系电话') {
+ $model->mobile = $prop['value'];
+ }
+ // 姓名
+ if ($prop['name'] === '您的姓名') {
+ $model->name = $prop['value'];
+ }
+ // // 意向车型
+ // if ($prop['name'] === '意向车型') {
+ // $model->vehicle = $prop['value'];
+ // }
+ // // 门店
+ // if ($prop['name'] === '选择门店') {
+ // $model->province = $prop['propertyExt']['address']['provinceName'] ?? '';
+ // $model->city = $prop['propertyExt']['address']['cityName'] ?? '';
+ // $model->dealer = $prop['value'] ?? '';
+ // $model->dealer_code = $prop['outCode'];
+ // }
+ }
+ $model->save();
+ return $model;
+ }
+
+ public static function cluepackage($data)
+ {
+ // {
+ // "id": "5100421",
+ // "sign": "M9XNP7B49mldvBqGkASL/PFp/0HITi7zwShy78FzArS9H+3WuUTNewy3QIIwMhWXS5sEaePjw5BtC0A7xYO4pYP2HVCcospiOTXO5boz/Ki03xeY7OhbY1YrhI5fhYqgQOj6Efn2mM44ijtXzMh4phDMgcu0e1HcgQFTDvIgAZZ5D6IvXyLR245WGMjSDnyqtMJj87MCrTj6ZmkfiLKvGH8mSWtKd0WFS6UgfQIs/Rruw0ZQNT5+mawTT8CZE1Va3Wt0xGc6CegeNtI4f/eFNHsqgppwXO0dtKPcWRZeNvNYUqQT1G9M1epC6lvxdPD+rr8i6SEVaBkxmQVF+eN8Iw==",
+ // "method": "spi.alipay.data.dataservice.ad.cluepackage.send",
+ // "charset": "UTF-8",
+ // "version": "1.0",
+ // "clue_time": "2024-08-26 22:11:59",
+ // "sign_type": "RSA2",
+ // "user_city": "河北省",
+ // "user_name": "滏",
+ // "extend_info": "{\"brandName\":\"奇瑞\",\"merchantId\":\"23408\",\"seriesName\":\"瑞虎8L\",\"merchantName\":\"唐山荣泽\"}",
+ // "user_province": "唐山市",
+ // "utc_timestamp": "1724681530",
+ // "user_mobile_no": "15318418738"
+ // }
+
+ // $externalId = $data['id'];
+ // $model = static::query()->where('external_id', $externalId)->first();
+ // if ($model) {
+ // info('===== cluepackage exists', $data);
+ // return $model;
+ // }
+ $model = new static(['source' => 'cluepackage', 'rawdata' => $data]);
+ $model->name = $data['user_name'] ?? '';
+ $model->mobile = $data['user_mobile_no'] ?? '';
+ $model->meta = $data['extend_info'] ?? [];
+ $model->save();
+
+ return $model;
+ }
}
diff --git a/packages/bydauto/src/Models/Vehicle.php b/packages/bydauto/src/Models/Vehicle.php
index 32c7200..39fff41 100644
--- a/packages/bydauto/src/Models/Vehicle.php
+++ b/packages/bydauto/src/Models/Vehicle.php
@@ -31,14 +31,14 @@ public function dealers()
public static function cachedItems()
{
return Cache::remember('BYDAuto:vechicle', 3600, function () {
- return Vehicle::query()->get()->map(fn($d) => ['id' => $d->id, 'name' => $d->name, 'alias' => $d->alias, 'spec_id' => $d->spec_id]);
+ return Vehicle::query()->get()->map(fn ($d) => ['id' => $d->id, 'name' => $d->name, 'alias' => $d->alias, 'spec_id' => $d->spec_id]);
});
}
public static function specId($name)
{
$items = self::cachedItems();
- $item = $items->first(fn($d) => in_array($name, $d['alias']) || $d['name'] === $name);
+ $item = $items->first(fn ($d) => in_array($name, $d['alias']) || $d['name'] === $name);
return $item ? $item['spec_id'] : null;
}
}
diff --git a/packages/bydauto/src/Notifications/TestdirveNotification.php b/packages/bydauto/src/Notifications/TestdirveNotification.php
index ba1fbff..95610e2 100644
--- a/packages/bydauto/src/Notifications/TestdirveNotification.php
+++ b/packages/bydauto/src/Notifications/TestdirveNotification.php
@@ -4,18 +4,15 @@
use BYDAuto\Models\Testdrive;
use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
+use Illuminate\Support\HtmlString;
class TestdirveNotification extends Notification
{
use Queueable;
- public function __construct(protected Testdrive $model)
- {
- //
- }
+ public function __construct(protected Testdrive $model) {}
public function via(object $notifiable): array
{
@@ -25,8 +22,8 @@ public function via(object $notifiable): array
public function toMail(object $notifiable): MailMessage
{
$text = sprintf("姓名:%s
电话:%s", $this->model->name, $this->model->mobile, $this->model->mobile);
- $text = new \Illuminate\Support\HtmlString($text);
- return (new MailMessage)
+ $text = new HtmlString($text);
+ return (new MailMessage())
->subject("预约试驾线索通知")
->line("收到一条新的试驾预约信息")
->line($text)
@@ -37,7 +34,6 @@ public function toMail(object $notifiable): MailMessage
public function toArray(object $notifiable): array
{
return [
- //
];
}
}