目前还没有画面可以看或操作,所以单就资料流的部分先写进资料库,
而建立订单目前也是先塞变数进去,所以每次都会是新单。
今天的目标就是写进资料库,并产生一个简单的表格来看(最阳春的那种)
主要记录的有几个栏位
OrderNo
- 订单编号Amonut
- 订单金额PrdtName
- 顾客名称PayType
- 付款方式ExpireDate
- 订单逾期日期AutoBilling
- 是否自动请款ExpBillingDays
- 自动请款天数TSNo
- 交易编号Status
- 处理状态Description
- 回应讯息AtmPayNo
- 虚拟帐号WebAtmURL
- Web ATM 网址OtpURL
- 一次性密码网址CardPayURL
- 信用卡付款网址之前规划的栏位已经有了 [订单编号
, 订单总金额
, 付款方式
, 订单状态
, 订单过期日期
],
还缺少 [顾客名称
, 是否自动请款
, 自动请款天数
, 交易编号
, 回应讯息
, 虚拟帐号
, Web ATM 网址
, 一次性密码网址
, 信用卡付款网址
]
> php artisan make:migration --table=sale_orders update_sale_order
// database/migrations/[current_date_time]_update_sale_order.php
public function up()
{
Schema::table('sale_orders', function (Blueprint $table) {
$table->string('prdt_name', 50)->comment('顾客名称');
$table->string('auto_billing', 1)->nullable()->comment('是否自动请款');
$table->tinyInteger('exp_billing_days')->nullable()->comment('自动请款天数');
$table->string('ts_no', 20)->nullable(false)->comment('交易编号');
$table->string('description', 50)->nullable()->comment('回应讯息');
$table->string('atm_pay_no', 14)->nullable()->comment('虚拟帐号');
$table->string('web_atm_url', 255)->nullable()->comment('Web ATM 网址');
$table->string('otp_url', 255)->nullable()->comment('一次性密码网址');
$table->string('card_pay_url', 255)->nullable()->comment('信用卡付款网址');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('sale_orders', function (Blueprint $table) {
$table->dropColumn(['prdt_name', 'auto_billing', 'exp_billing_days', 'ts_no', 'description', 'atm_pay_no', 'web_atm_url', 'otp_url', 'card_pay_url']);
});
}
// database/migrations/[create_date_time]_create_sale_orders_table.php
...
$table->dateTime('pay_datetime')->nullable()->comment('付款时间');
...
> php artisan migrate:fresh
(此工具为 PhpStorm 的 Database,在开发的时候能检查SQL语法对应的表格或栏位,非工商 XD)
// app/Models/sale_order.php
protected $fillable = [
...
'prdt_name',
'auto_billing',
'exp_billing_days',
'ts_no',
'description',
'atm_pay_no',
'web_atm_url',
'otp_url',
'card_pay_url'
];
public function create_order(Request $request)
{
$sinopac = $this->initSinopac();
$order_no = date('YmdHis');
$amount = random_int(4000, 10000);
$pay_type = ($request->get('credit', '') === 'Y') ? 'C' : 'A';
$expire_date = date('Ymd', time() + 604800);
$data = [
'ShopNo' => $sinopac->shop_no,
'OrderNo' => $order_no,
'Amount' => $amount . '00',
'CurrencyID' => 'TWD',
'PrdtName' => '大河',
'ReturnURL' => 'http://10.11.22.113:8803/QPay.ApiClient-Sandbox/Store/Return',
'BackendURL' => 'https://sandbox.sinopac.com/funBIZ.ApiClient/AutoPush/PushSuccess',
'PayType' => $pay_type,
'ATMParam' => [
'ExpireDate' => $expire_date,
],
];
$data = $sinopac->requestDataset('OrderCreate', $data);
$message = $sinopac->callApi('https://apisbx.sinopac.com/funBIZ/QPay.WebAPI/api/Order', $data);
$reply_nonce = $message['Nonce'] | '';
if (!$reply_nonce) {
$msg = 'Reply message haven\'t Nonce';
Log::error($msg , $message);
throw new \Exception($msg);
}
// 1. nonce 计算 iv
$iv = $sinopac->calculateIv($reply_nonce);
// 2. 计算 hash_id (AES key)
$hash_id = $sinopac->calcHashId();
// 3. message 解密
$decrypt_message = $sinopac->decryptMessage($message['Message'], $hash_id, $iv);
// 4. 验证 sign
$sign = $sinopac->generateSign($decrypt_message, $reply_nonce, $hash_id);
if (!($sign === $message['Sign'])) {
return ['msg' => '验证错误,内文签章不同'];
}
// 这里的 – 是 \xE2 不是 \x2D
$description = explode(' – ', $decrypt_message['Description']);
if ($description[0] !== 'S0000') {
Log::alert('订单未建立成功', $decrypt_message);
}
$dataset = [
'customer_id' => 0,
'order_no' => $order_no,
'total' => $amount,
'pay_type' => $pay_type,
'expire_date' => $expire_date,
'ts_no' => $decrypt_message['TSNo'],
'status' => $decrypt_message['Status'],
'description' => $decrypt_message['Description'],
'mailing_address' => '',
'prdt_name' => '大河',
];
if ($pay_type === 'C') {
// 信用卡
$card_param = $decrypt_message['CardParam'];
$dataset = array_merge($dataset, [
'card_pay_url' => $card_param['CardPayURL'],
]);
} else {
// 虚拟帐号
$atm_param = $decrypt_message['ATMParam'];
$dataset = array_merge($dataset, [
'atm_pay_no' => $atm_param['AtmPayNo'],
'web_atm_url' => $atm_param['WebAtmURL'],
'otp_url' => $atm_param['OtpURL'],
]);
}
$id = sale_order::create($dataset)->id;
return [
'dataset' => $dataset,
'id' => $id
];
}
> php .\artisan make:controller Web
// app/Http/Controllers/Web.php
public function orders()
{
return view('orders', [
'dataset' => sale_order::all()->toArray()
]);
}
resources/views
建立 orders.blade.php
// resources/views/orders.blade.php
<style>
table {
width: 100%;
text-align: center;
}
thead > tr, tr:hover {
background: #1a202c30;
}
</style>
<table>
<thead>
<tr>
<th>#</th>
<th>订单编号</th>
<th>订单金额</th>
<th>订单类型</th>
<th>客户名称</th>
<th>客户住址</th>
<th>处理状态</th>
<th>银行回覆内容</th>
<th>付款期限</th>
<th>建立日期</th>
<th>更新日期</th>
</tr>
</thead>
<tbody>
@foreach($dataset as $index => $line)
<tr>
<td>{{ $index + 1 }}</td>
<td>{{ $line['order_no'] }}</td>
<td>{{ $line['total'] }}</td>
<td>{{ $line['pay_type'] }}</td>
<td>{{ $line['prdt_name'] }}</td>
<td>{{ $line['mailing_address'] }}</td>
<td>{{ $line['status'] }}</td>
<td>{{ $line['description'] }}</td>
<td>{{ $line['expire_date'] }}</td>
<td>{{ $line['created_at'] }}</td>
<td>{{ $line['updated_at'] }}</td>
</tr>
@endforeach
</tbody>
</table>
// routes/web.php
Route::get('/orders', [Web::class, 'orders']);
OK~来看个成果
差点赶不上发文阿,要改的bug好多阿,有点怀疑自己为什麽要参赛了
明天要把让自己轻松一些,简单看一下回应的网页长怎麽样好了 ('web_atm_url', 'otp_url', 'card_pay_url')
那昨天安装好路由器後,我们要来架设一下 VPN。 在此之前,我们今天先来说明一下 VPN 是什麽。 ...
昨天我们完成了用Flask撰写ticks API, API端好了之後,接下来我们要开始架设我们的cl...
平常都用惯 TypeScript 版的 Cypress,但这两天都用 JavaScript 在写测...
由於目前人在美东,与台湾的时差刚好 12hr,完全可以说出:「当我在睡觉时,台湾的大家都还在认真工作...
npm install --save (产品用) npm install --save-dev (开...