diff --git a/config/peachpayment.php b/config/peachpayment.php index 4938930..ac45e72 100644 --- a/config/peachpayment.php +++ b/config/peachpayment.php @@ -15,6 +15,9 @@ 'api_uri_live' => 'https://oppwa.com/', 'api_uri_version' => 'v1/', 'skip_3ds_for_stored_cards' => true, + 'webhook_url' => '/peach-webhook', + 'webhook_excluded' => ['card', 'authentication'], + 'webhook_secret_key' => env('PEACH_PAYMENTS_WEBHOOK_SECRET_KEY'), ]; } @@ -32,4 +35,7 @@ 'api_uri_live' => 'https://oppwa.com/', 'api_uri_version' => 'v1/', 'skip_3ds_for_stored_cards' => true, + 'webhook_url' => '/peach-webhook', + 'webhook_excluded' => ['card', 'authentication'], + 'webhook_secret_key' => env('PEACH_PAYMENTS_WEBHOOK_SECRET_KEY'), ]; diff --git a/database/migrations/create_payment_events_table.php.stub b/database/migrations/create_payment_events_table.php.stub new file mode 100644 index 0000000..0820b6e --- /dev/null +++ b/database/migrations/create_payment_events_table.php.stub @@ -0,0 +1,35 @@ +bigIncrements('id'); + $table->string('type'); + $table->string('action')->nullable(); + $table->text('payload'); + $table->timestamps(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('payment_events'); + } +} diff --git a/readme.md b/readme.md index c81c0a3..706d3d4 100644 --- a/readme.md +++ b/readme.md @@ -94,6 +94,16 @@ $response->isValidationError($resultCode); // true|false Saving the response is also available: `$response->save($result, $paymentCard);` +### Webhooks + +The following change needs to be made in your `app/Http/Middleware/VerifyCsrfToken.php` file: + +```php +protected $except = [ + config('peachpayment.webhook_url') + ]; +``` + ### Helpers #### Setting.php This class allows you to inject or modify your Peach Payment credentials diff --git a/routes/web.php b/routes/web.php new file mode 100644 index 0000000..99699e1 --- /dev/null +++ b/routes/web.php @@ -0,0 +1,7 @@ +name('peachpayment.index'); diff --git a/src/Http/Controllers/Controller.php b/src/Http/Controllers/Controller.php new file mode 100644 index 0000000..c666710 --- /dev/null +++ b/src/Http/Controllers/Controller.php @@ -0,0 +1,13 @@ +model = $model; + } + + public function index(Request $request) + { + $event = new PaymentEvent(); + $body = $this->decryptMessage($request); + $payload = $body['payload']; + + $excludedValues = Config::get('peachpayment.webhook_excluded'); + + foreach ($excludedValues as $exclude) { + unset($payload[$exclude]); + } + + $event->type = $body['type']; + $event->action = $body['action']; + $event->payload = $payload; + $event->save(); + + return response([], Response::HTTP_OK); + } + + private function decryptMessage(Request $request) + { + $keyFromConfiguration = Config::get('peachpayment.webhook_secret_key'); + $ivFromHeader = $request->header('X-Initialization-Vector'); + $authTagFromHeader = $request->header('X-Authentication-Tag'); + + $key = hex2bin($keyFromConfiguration); + $iv = hex2bin($ivFromHeader); + $authTag = hex2bin($authTagFromHeader); + $cipherText = hex2bin($request->getContent()); + + $result = openssl_decrypt($cipherText, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $authTag) + + return json_decode($result, true); + } +} diff --git a/src/Models/PaymentEvent.php b/src/Models/PaymentEvent.php new file mode 100644 index 0000000..a13e0f2 --- /dev/null +++ b/src/Models/PaymentEvent.php @@ -0,0 +1,21 @@ + 'array', + ]; +} diff --git a/src/PeachPaymentServiceProvider.php b/src/PeachPaymentServiceProvider.php index 17d5422..945bb3e 100644 --- a/src/PeachPaymentServiceProvider.php +++ b/src/PeachPaymentServiceProvider.php @@ -22,7 +22,10 @@ public function boot() $this->publishes([ __DIR__.'/../database/migrations/create_payment_cards_table.php.stub' => database_path('migrations/' . date('Y_m_d_His', time()) . '_create_payment_cards_table.php'), __DIR__.'/../database/migrations/create_payment_results_table.php.stub' => database_path('migrations/' . date('Y_m_d_His', time()) . '_create_payment_results_table.php'), + __DIR__.'/../database/migrations/create_payment_events_table.php.stub' => database_path('migrations/' . date('Y_m_d_His', time()) . '_create_payment_events_table.php'), ], 'peachpayment-migrations'); + + $this->loadRoutesFrom(__DIR__.'/../routes/web.php'); } } diff --git a/tests/Unit/WebhookTest.php b/tests/Unit/WebhookTest.php new file mode 100644 index 0000000..e7e2f80 --- /dev/null +++ b/tests/Unit/WebhookTest.php @@ -0,0 +1,31 @@ +artisan('migrate'); + } + + /** + * @test + */ + public function it_can_receive_an_event() + { + $response = $this->postJson(route('peachpayment.index'), []); + + $response->assertOk(); + } +}