Skip to content

Commit 278a4cd

Browse files
committed
Add duitnow requeries
1 parent c400adc commit 278a4cd

File tree

7 files changed

+203
-2
lines changed

7 files changed

+203
-2
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
public function up()
10+
{
11+
Schema::create('duitnow_qr_requeries', function (Blueprint $table) {
12+
$table->id();
13+
$table->foreignId('transaction_id')->nullable()
14+
->constrained(
15+
table: 'duitnow_qr_transactions'
16+
)->onUpdate('set null')->onDelete('set null');
17+
$table->string('source_reference_number', 100)->nullable();
18+
$table->date('transaction_date')->nullable();
19+
$table->time('transaction_time_start')->nullable()->default(0);
20+
$table->time('transaction_time_end')->nullable()->default(0);
21+
$table->json('response_payload')->nullable();
22+
$table->string('status_code', 5)->nullable();
23+
$table->timestamps();
24+
});
25+
}
26+
27+
/**
28+
* Reverse the migrations.
29+
*
30+
* @return void
31+
*/
32+
public function down()
33+
{
34+
Schema::dropIfExists('duitnow_qr_requeries');
35+
}
36+
};

src/Data/Callback.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ private function storePayment()
6666
$this->duitnow_qr_transaction?->payments()->create($this->toArray());
6767
}
6868

69-
public function excludeProperties() : array
69+
public function excludeProperties(): array
7070
{
7171
return [
7272
'payment_date',

src/Data/Requery.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace ZarulIzham\DuitNowQR\Data;
4+
5+
use Spatie\LaravelData\Attributes\MapInputName;
6+
use Spatie\LaravelData\Data;
7+
8+
class Requery extends Data
9+
{
10+
public function __construct(
11+
12+
#[MapInputName('EndID')]
13+
public string $end_id,
14+
15+
#[MapInputName('BizID')]
16+
public string $biz_id,
17+
18+
#[MapInputName('QRString')]
19+
public ?string $qr_string,
20+
21+
#[MapInputName('TransactionStatus')]
22+
public string $transaction_status,
23+
24+
#[MapInputName('Reason')]
25+
public ?string $reason,
26+
27+
#[MapInputName('SenderName')]
28+
public string $sender_name,
29+
30+
#[MapInputName('TrxAmount')]
31+
public float $amount,
32+
33+
#[MapInputName('TrxCurrency')]
34+
public string $currency,
35+
36+
#[MapInputName('AccNo')]
37+
public string $account_number,
38+
39+
#[MapInputName('PaymentDt')]
40+
public string $payment_date,
41+
42+
#[MapInputName('PaymentHrs')]
43+
public string $payment_time,
44+
45+
#[MapInputName('SourceofFund')]
46+
public string $source_of_fund,
47+
) {}
48+
}

src/DuitNowQR.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace ZarulIzham\DuitNowQR;
44

5+
use Carbon\Carbon;
6+
use Exception;
57
use Illuminate\Support\Facades\Cache;
68
use Illuminate\Support\Facades\Http;
79
use ZarulIzham\DuitNowQR\Exceptions\BadRequest;
@@ -146,6 +148,60 @@ public function getStatus($qrString, $transactionDate)
146148
return $response->json();
147149
}
148150

151+
public function getStatusByTransaction(DuitNowQRTransaction $duitNowQRTransaction, Carbon $transactionDate, $transactionTimeStart, $transactionTimeEnd)
152+
{
153+
$token = Cache::remember('duitnow_qr_token', config('duitnowqr.token_expiry'), fn () => $this->authenticate());
154+
155+
$sourceReferenceNumber = $this->getSrcRefNo();
156+
$url = config('duitnowqr.url')."/api/MerchantQR/v1.0/GetQTNotification/$sourceReferenceNumber";
157+
158+
$ambankTimestamp = now()->format('dmYHis');
159+
160+
$headers = [
161+
'Authorization' => 'Bearer '.$token,
162+
'Authentication' => $token,
163+
'AmBank-Timestamp' => $ambankTimestamp,
164+
'Channel-Token' => config('duitnowqr.channel_token'),
165+
'srcRefNo' => $sourceReferenceNumber,
166+
'Content-Type' => 'application/json',
167+
'Accept' => 'application/json',
168+
'Channel-APIKey' => config('duitnowqr.api_key'),
169+
];
170+
171+
try {
172+
$transactionTimeStart = $transactionDate->clone()->setTimeFromTimeString($transactionTimeStart);
173+
$transactionTimeEnd = $transactionDate->clone()->setTimeFromTimeString($transactionTimeEnd);
174+
} catch (\Throwable $th) {
175+
throw new Exception('Failed to read transaction time. Please use format H:i (Eg: 23:00)');
176+
}
177+
178+
$body = [
179+
'QRString' => $duitNowQRTransaction->qr_string,
180+
'TrxDate' => $transactionDate->format('d/m/Y'),
181+
'TrxTimeStart' => $transactionTimeStart->format('H:i'),
182+
'TrxTimeEnd' => $transactionTimeEnd->format('H:i'),
183+
];
184+
185+
$bodyEscaped = str_replace('\\', '', json_encode($body));
186+
187+
$headers['Ambank-Signature'] = $this->signature('/api/MerchantQR/v1.0/GetQTNotification/'.$sourceReferenceNumber, $ambankTimestamp, $body);
188+
189+
$response = null;
190+
try {
191+
$response = Http::withHeaders($headers)->withOptions([
192+
'debug' => false,
193+
])
194+
->withBody($bodyEscaped, 'application/json')
195+
->post($url);
196+
} catch (\Throwable $th) {
197+
//throw $th;
198+
}
199+
200+
$this->storeRequeryStatus($duitNowQRTransaction, $sourceReferenceNumber, $transactionTimeStart, $transactionTimeEnd, $response);
201+
202+
return $response->json();
203+
}
204+
149205
public function signature($uri, $ambankTimestamp, $body): string
150206
{
151207
$header = [
@@ -167,4 +223,16 @@ public function signature($uri, $ambankTimestamp, $body): string
167223

168224
return $base64;
169225
}
226+
227+
public function storeRequeryStatus($duitNowQRTransaction, $sourceReferenceNumber, $transactionTimeStart, $transactionTimeEnd, $response)
228+
{
229+
$duitNowQRTransaction->requeries()->create([
230+
'source_reference_number' => $sourceReferenceNumber,
231+
'status_code' => $response?->status(),
232+
'response_payload' => $response?->body(),
233+
'transaction_date' => $transactionTimeStart->format('Y-m-d'),
234+
'transaction_time_start' => $transactionTimeStart->format('H:i:s'),
235+
'transaction_time_end' => $transactionTimeEnd->format('H:i:s'),
236+
]);
237+
}
170238
}

src/DuitNowQRServiceProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ public function configurePackage(Package $package): void
1919
->hasCommand('ZarulIzham\DuitNowQR\Commands\DuitNowQRCommand')
2020
->name('laravel-duitnow-qr')
2121
->hasConfigFile('duitnowqr')
22-
->hasMigrations('create_duitnow_qr_transactions', 'create_duitnow_qr_payments');
22+
->hasMigrations('create_duitnow_qr_transactions', 'create_duitnow_qr_payments', 'create_duitnow_qr_requeries');
2323
}
2424
}

src/Models/DuitNowQRRequery.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace ZarulIzham\DuitNowQR\Models;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
use Illuminate\Support\Collection;
7+
use ZarulIzham\DuitNowQR\Data\Requery;
8+
9+
class DuitNowQRRequery extends Model
10+
{
11+
protected $table = 'duitnow_qr_requeries';
12+
13+
protected $fillable = [
14+
'transaction_id',
15+
'source_reference_number',
16+
'transaction_date',
17+
'transaction_time_start',
18+
'transaction_time_end',
19+
'status_code',
20+
'response_payload',
21+
];
22+
23+
/**
24+
* The attributes that should be cast to native types.
25+
*
26+
* @var array
27+
*/
28+
protected $casts = [
29+
'transaction_date' => 'date',
30+
'response_payload' => 'array',
31+
];
32+
33+
public function getResponseAttribute()
34+
{
35+
if ($this->status_code == '200') {
36+
return Requery::collect($this->response_payload, Collection::class);
37+
}
38+
39+
return $this->response_payload;
40+
}
41+
}

src/Models/DuitNowQRTransaction.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,12 @@ public function reference(): MorphTo
4040
{
4141
return $this->morphTo();
4242
}
43+
44+
/**
45+
* Get all of the requeries for the DuitNowQRTransaction
46+
*/
47+
public function requeries(): HasMany
48+
{
49+
return $this->hasMany(DuitNowQRRequery::class, 'transaction_id');
50+
}
4351
}

0 commit comments

Comments
 (0)