init
All checks were successful
Deploy to Production / deploy (push) Successful in 15s

This commit is contained in:
梁朝伟 2024-11-14 18:16:27 +08:00
parent 4c72a02669
commit d3923edd75
11 changed files with 176 additions and 55 deletions

View File

@ -4,8 +4,7 @@
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
return new class extends Migration return new class extends Migration {
{
public function up(): void public function up(): void
{ {
Schema::create('bydauto_contact', function (Blueprint $table) { Schema::create('bydauto_contact', function (Blueprint $table) {

View File

@ -11,4 +11,7 @@
Route::get('province', [BYDAutoController::class, 'province']); Route::get('province', [BYDAutoController::class, 'province']);
Route::get('city', [BYDAutoController::class, 'city']); Route::get('city', [BYDAutoController::class, 'city']);
Route::post('testdrive', [BYDAutoController::class, 'testdrive']); Route::post('testdrive', [BYDAutoController::class, 'testdrive']);
Route::post('isaas', [BYDAutoController::class, 'isaas']);
Route::post('cluepackage', [BYDAutoController::class, 'cluepackage']);
Route::post('notice', [BYDAutoController::class, 'notice']);
}); });

View File

@ -3,8 +3,8 @@
namespace BYDAuto\Controllers; namespace BYDAuto\Controllers;
use BYDAuto\Actions\TestdriveCreateAction; use BYDAuto\Actions\TestdriveCreateAction;
use BYDAuto\Models\Dealer; use BYDAuto\Foundation\Encryption;
use BYDAuto\Models\Vehicle; use BYDAuto\Models\Testdrive;
use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Routing\Controller; use Illuminate\Routing\Controller;
@ -29,41 +29,71 @@ public function testdrive(Request $request)
return response()->json(['code' => 0, 'message' => '提交成功', 'request_id' => $requestId]); 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(); $input = $request->all();
return response()->json($items); info('===== bydautoController::isaas', $input);
$biz_content = $input['biz_content'] ?? '';
throw_if(empty($biz_content), ValidationException::withMessages(['biz_content' => 'missing biz_content']));
$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()]);
}
// 留咨成功 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 province(Request $request) // 实现官方标准API 专享产品-灯火平台广告投放
// 提供给特定广告代理商(例如 天猫),为广告主提供广告投放服务
// https://vm1112app.arsk.net/pkg/bydauto/cluepackage
// 官方定义的标准API 行业线索数据推送
public function cluepackage(Request $request)
{ {
$vehicle = Vehicle::query()->firstWhere('name', $request->vehicle); Testdrive::cluepackage($request->all());
$dealers = $vehicle->dealers; return response()->json(['response' => ['code' => '10000', 'msg' => 'Success']]);
$province = $dealers->groupBy('province')->keys();
$data = $province->map(fn($item) => ['name' => $item]);
return response()->json($data);
} }
public function city(Request $request) // 支付宝支付通知应用网关https://vm1112app.arsk.net/pkg/bydauto/notice
// 用于接收支付宝异步通知消息例如From平台消息等需要传入http(s)公网可访问的网页地址。选填,若不设置,则无法接收相应的异步通知消息
public function notice(Request $request)
{ {
$vehicle = Vehicle::query()->firstWhere('name', $request->vehicle); $input = $request->all();
if (!$vehicle) { info('===== notice', $input);
throw ValidationException::withMessages(['vehicle' => '车型不存在']); return response('');
}
$dealers = $vehicle->dealers;
$city = $dealers->where('province', $request->province)->groupBy('city')->keys();
$data = $city->map(fn($item) => ['name' => $item]);
return response()->json($data);
} }
public function dealer(Request $request) protected function sign($input)
{ {
$vehicle = Vehicle::query()->firstWhere('name', $request->vehicle); $pubkey = file_get_contents(storage_path('app/pkg/chery-crm/isaas/app_pub_RSA2048.txt'));
if (!$vehicle) { $pubkey = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($pubkey, 64, "\n", true) . "\n-----END PUBLIC KEY-----";
throw ValidationException::withMessages(['vehicle' => '车型不存在']);
$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);
} }
$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]); protected function encrypt($input, $key)
return response()->json($data); {
$iv = str_repeat("\0", 16);
return base64_encode(openssl_encrypt($input, 'AES-256-CBC', base64_decode($key), OPENSSL_RAW_DATA, $iv));
} }
} }

View File

@ -5,7 +5,7 @@
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
* Activity * Activity.
* *
* @property int id * @property int id
* @property string name * @property string name
@ -16,7 +16,10 @@
class Activity extends Model class Activity extends Model
{ {
public $timestamps = false; public $timestamps = false;
protected $table = 'bydauto_activity'; protected $table = 'bydauto_activity';
protected $fillable = ['name', 'content', 'related_id', 'related_type']; protected $fillable = ['name', 'content', 'related_id', 'related_type'];
protected $casts = ['content' => 'json']; protected $casts = ['content' => 'json'];
} }

View File

@ -9,10 +9,15 @@ class Contact extends Model
{ {
use Notifiable; use Notifiable;
const STATUS_PUBLISHED = 'published'; public const STATUS_PUBLISHED = 'published';
const STATUS_DRAFT = 'draft';
public const STATUS_DRAFT = 'draft';
public const CREATED_AT = 'date_created'; public const CREATED_AT = 'date_created';
public const UPDATED_AT = 'date_updated'; public const UPDATED_AT = 'date_updated';
protected $table = 'bydauto_contact'; protected $table = 'bydauto_contact';
protected $fillable = ['remark', 'email', 'status']; protected $fillable = ['remark', 'email', 'status'];
} }

View File

@ -2,8 +2,8 @@
namespace BYDAuto\Models; namespace BYDAuto\Models;
use Carbon\Carbon;
use BYDAuto\Observers\TestdriveObserver; use BYDAuto\Observers\TestdriveObserver;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Attributes\ObservedBy; use Illuminate\Database\Eloquent\Attributes\ObservedBy;
use Illuminate\Database\Eloquent\Model; 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 $fillable = ['status', 'name', 'mobile', 'platform', 'source', 'meta', 'rawdata', 'request_id'];
protected $casts = ['meta' => 'json', 'rawdata' => 'json']; 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;
}
} }

View File

@ -4,18 +4,15 @@
use BYDAuto\Models\Testdrive; use BYDAuto\Models\Testdrive;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification; use Illuminate\Notifications\Notification;
use Illuminate\Support\HtmlString;
class TestdirveNotification extends Notification class TestdirveNotification extends Notification
{ {
use Queueable; use Queueable;
public function __construct(protected Testdrive $model) public function __construct(protected Testdrive $model) {}
{
//
}
public function via(object $notifiable): array public function via(object $notifiable): array
{ {
@ -25,8 +22,8 @@ public function via(object $notifiable): array
public function toMail(object $notifiable): MailMessage public function toMail(object $notifiable): MailMessage
{ {
$text = sprintf("姓名:%s <br>电话:<a href='tel:%s'>%s</a>", $this->model->name, $this->model->mobile, $this->model->mobile); $text = sprintf("姓名:%s <br>电话:<a href='tel:%s'>%s</a>", $this->model->name, $this->model->mobile, $this->model->mobile);
$text = new \Illuminate\Support\HtmlString($text); $text = new HtmlString($text);
return (new MailMessage) return (new MailMessage())
->subject("预约试驾线索通知") ->subject("预约试驾线索通知")
->line("收到一条新的试驾预约信息") ->line("收到一条新的试驾预约信息")
->line($text) ->line($text)
@ -37,7 +34,6 @@ public function toMail(object $notifiable): MailMessage
public function toArray(object $notifiable): array public function toArray(object $notifiable): array
{ {
return [ return [
//
]; ];
} }
} }