From 8bcfce64c2fed218f94bfcf3a92c638fdebfa03c Mon Sep 17 00:00:00 2001 From: Jeremiah Ikwuje Date: Mon, 16 Nov 2020 15:28:58 +0100 Subject: [PATCH] Troubleshoot rave webhook --- CHANGELOG.md | 7 + src/Helpers/DoSomething.php | 19 +- src/Processors/Flutterwave/Transaction.php | 261 +++++++++++---------- src/Processors/Paystack/Transaction.php | 35 ++- tests/config.php | 2 +- tests/hook.txt | 1 - tests/index.php | 21 +- tests/ref.txt | 1 - tests/results/hook.txt | 1 + tests/results/ref.txt | 1 + tests/results/verify.txt | 1 + tests/test.txt | 0 tests/verify.php | 13 +- tests/webhook.php | 15 +- 14 files changed, 217 insertions(+), 161 deletions(-) delete mode 100644 tests/hook.txt delete mode 100644 tests/ref.txt create mode 100644 tests/results/hook.txt create mode 100644 tests/results/ref.txt create mode 100644 tests/results/verify.txt delete mode 100644 tests/test.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d5483b..d317235 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,3 +5,10 @@ All notable changes to `abegpay-php` will be documented in this file ## 1.0.0 - 201X-XX-XX - initial release + + +You change the following: + +Remove the code that set the email should incase the user didn't set pass an email through the $body parameter. +Does flutterwave has callback_url, isn't it redirect_url + diff --git a/src/Helpers/DoSomething.php b/src/Helpers/DoSomething.php index 089b259..a62928f 100644 --- a/src/Helpers/DoSomething.php +++ b/src/Helpers/DoSomething.php @@ -1,17 +1,17 @@ null, 'email' => null, 'phone' => null @@ -60,14 +60,6 @@ class Transaction extends Flutterwave */ protected $body; - /** - * request body nexted array value - * - * @var array - * @since 0.5 - */ - protected $customer; - /** * The transacion endpoint * @@ -107,14 +99,6 @@ class Transaction extends Flutterwave */ protected $payment_option = 'card'; - /** - * local hash to check against event Hash - * - * @var string - * @since 0.5 - */ - protected $webhookHash; - /** * Constructor * @@ -136,29 +120,27 @@ public function setEmail(string $email): void if (! DoSomething::goodEmail($email)) { throw new PayException('Transaction: Email is not valid'); } - $this->payer['email'] = $email; + $this->customer['email'] = $email; } /** - * Set the Payer information + * Set the customer information * * @since 0.5 */ - public function setPayer(array $payer): void + public function setCustomer(array $customer): void { - if (! array_key_exists('email', $payer)) { - throw Exception('Payer email is required'); + if( isset($this->customer['email']) ) { + $this->customer['email'] = $customer['email']; } - - $this->payer['email'] = $payer['email']; - - if ( array_key_exists('name', $payer) ) { - $this->payer['name'] = $payer['name']; - } - - if ( array_key_exists('phone', $payer) ) { - $this->payer['phone'] = $payer['phone']; + else { + if( !$this->getEmail() ) { + throw Exception('customer email is required'); + } } + + $this->customer['phone'] = $customer['phone'] ?? null; + $this->customer['name'] = $customer['name'] ?? null; } /** @@ -169,7 +151,7 @@ public function setPayer(array $payer): void public function setCurrency(string $currency): void { if (! in_array($currency, $this->currencies)) { - throw new PayException('Transaction: Currency not supported by Paystack'); + throw new PayException('Transaction: Currency not supported by Flutterwave'); } $this->currency = $currency; @@ -255,7 +237,7 @@ public function getAmount(): float */ public function getEmail(): string { - return ($this->payer['email'] ?? ''); + return $this->customer['email']; } /** @@ -273,9 +255,9 @@ public function getEndpoint(): string * * @since 0.5 */ - public function getPayer(): array + public function getCustomer(): object { - return $this->payer; + return (object) $this->customer; } /** @@ -329,89 +311,133 @@ public function getReference(): string } /** - * Initialize a Paystack transaction + * Initialize a Flutterwave transaction * * --------------------------------------------------------------------- * We make a request to the /transaction endpoint * a response will be returned: * { * ... - * "authorization_url": "https://checkout.paystack.com/0peioxfhpn", - * "access_code": "0peioxfhpn", - * "reference": "7PVGX8MEk85tgeEpVDtD" + * } * * We then set this response body * * @param $redirect if it set to true, we redirect to the PSTK checkout page - * @link https://paystack.com/docs/api/#transaction + * @link https://developer.flutterwave.com/docs/flutterwave-standard * @since 0.5 */ public function initialize(array $body = []) //: void { - if( array_key_exists('amount', $body) ) { $this->setAmount($body['amount']); } + else if( $this->getAmount() == 0 ) { + throw new PayException('Transaction: Amount is required on Flutterwave'); + } else { - if( $this->getAmount() == 0 ) { - throw new PayException('Amount is required for transaction'); + $body['amount'] = $this->getAmount(); + } + + if ( isset($body['customer']) && is_array($body['customer']) ) { + $customer = $body['customer']; + + if( isset($body['customer_email']) ) { + $this->setEmail( $body['customer_email'] ); + } + else if( !$this->getEmail() ) { + throw new PayException('Transaction: Customer email is required on Flutterwave'); } else { - $body['amount'] = $this->getAmount(); + $customer['email'] = $this->getEmail(); + } + + if( array_key_exists('phonenumber', $customer) ) { + $this->customer['phone'] = $customer['phonenumber']; + } + else if ( $this->customer['phone'] ) { + $customer['phonenumber'] = $this->customer['phone']; + } + + if( isset($customer['name']) ) { + $this->customer['name'] = $customer['name']; + } + else if( !$this->customer['name'] ) { + $customer['name'] = $this->customer['name']; } } + else { + $customer = []; + + if( array_key_exists('customer_email', $body) ) { + $this->setEmail($body['customer_email']); + $customer['email'] = $this->getEmail(); + } + else if( !$this->getEmail() ) { + throw new PayException('Transaction: Customer email is required on Flutterwave'); + } + else { + $customer['email'] = $this->getEmail(); + } + if( array_key_exists('customer_phone', $body) ) { + $customer['phonenumber'] = $body['customer_phone']; + } + else if ( $this->customer['phone'] ) { + $customer['phonenumber'] = $this->customer['phone']; + } - if( array_key_exists('email', $body) ) { - $this->setEmail($body['email']); - unset($body['email']); - } - else { - throw new PayException('Email is required for transaction'); + $name = sprintf( + '%s %s', + ($body['customer_firstname'] ?? ''), + ($body['customer_lastname'] ?? '') + ); // firstname lastname + + if( !empty($name) ) { + $customer['name'] = $name; + } + else if( $this->customer['name'] ) { + $customer['name'] = $this->customer['name']; + } } - if( array_key_exists('callback_url', $body) ) { + $body['customer'] = $customer; - // Reassign array with a new key - // unset the old array key - $this->setRedirect($body['redirect_url'] = $body['callback_url']); + if( array_key_exists('redirect_url', $body) ) { + $this->setRedirect($body['redirect_url']); + } + else if( !empty( $this->getRedirect()) ) { $body['redirect_url'] = $this->getRedirect(); - - unset($body['callback_url']); - } - if( array_key_exists('currency', $body) ) { $this->setCurrency($body['currency']); - $body['currency'] = $this->getCurrency(); } - else { - $body['currency'] = $this->currencies[0]; + else if( ! empty( $this->getCurrency()) ) { + $body['currency'] = $this->getCurrency(); } - - if( !$this->getPayer() ) { - $this->setPayer([ 'email' => $body['email'] ]); + if( array_key_exists('tx_ref', $body) ) { + $this->setReference($body['tx_ref']); + } + else if( !empty( $this->getReference()) ) { + $body['tx_ref'] = $this->getReference(); } else { - $body['customer'] = $this->getPayer(); + $body['tx_ref'] = bin2hex(random_bytes(7)); + $this->setReference($body['tx_ref']); } - $this->setReference( bin2hex(random_bytes(7)) ); - $body['tx_ref'] = $this->getReference(); - - $body['payment_options'] = $this->payment_option; + if( array_key_exists('payment_options', $body) ) { + $this->setReference($body['payment_options']); + } - $this->setBody($body); $request = $this->request; $request->post( sprintf('%s/payments', $this->getEndpoint()), $body ); - - if($request->error) { + if( $request->error ) { $this->httpStatusCode = $request->errorCode; $this->setMessage(); } @@ -435,7 +461,7 @@ public function initialize(array $body = []) //: void /** - * Redirect to paystack checkout page + * Redirect to Flutterwave checkout page * * @since 0.5 */ @@ -456,7 +482,7 @@ public function checkout(): void * If the transaction status was successfull, we return TRUE * ----------------------------------------------------------- * - * @link https://paystack.com/docs/api/#transaction-verify + * @link https://developer.flutterwave.com/v2.0/docs/rave-standard * @since 0.5 */ public function verify(string $reference = ''): void @@ -490,72 +516,58 @@ public function verify(string $reference = ''): void $this->setEmail($request->response->data->customer->email); $this->httpStatusCode = $request->getHttpStatusCode(); + $this->setMessage($request->response->message); - if('success' == $request->response->data->status) { + if('successful' == $request->response->data->status) { $this->status = true; + $this->setMessage($request->response->data->processor_response); } - - $this->setMessage($request->response->data->processor_response); } } - - /** - * Set webhook hash to check against event hash - * - * @link - * @since 0.5 - */ - public function webhookHash(string $hash) : void - { - $this->webhookHash = $hash; - } - /** * Handle webhook * - * When a transaction is made on Paystack, paystack sends a payload of + * When a transaction is made on Flutterwave, Flutterwave sends a payload of * data to URL you specify on your dashboard. * * This method handle the payload and return TRUE|FALSE for a * valid or non valid transaction. * - * @link https://paystack.com/docs/payments/webhooks/ + * @link https://developer.flutterwave.com/reference#webhook * @since 0.5 */ - public function webhook() + public function webhook(string $secretHash = '') : void { - - $checked = true; // default checked - - // check if webhook has isset else throw exception - if( !isset($this->webhookHash) ) { - throw new PayException('webhook secret hash is not set'); - } - // Retrieve the request's body $body = @file_get_contents("php://input"); + + $checked = true; // default checked - // confirm request method - if( (strtoupper($_SERVER['REQUEST_METHOD']) != 'POST' ) || !array_key_exists('HTTP_VERIF_HASH', $_SERVER) ) { + // if the has was provided + if( empty($hashCode) ) + { + throw new PayException('Secret hash is required. Check Settings/Webhook on your Flutterwave dashboard'); + exit(); + } - $checked = false; - $this->httpStatusCode = 400; - $this->message= 'Transaction: Invalid POST signature'; + if( ! isset($_SERVER['REQUEST_METHOD']) || strtoupper($_SERVER['REQUEST_METHOD']) != 'POST' ) + { + throw new PayException('Transaction: Invalid Flutterwave POST request'); + exit(); } - + // Retrieve event signature hash $eventHash = (isset($_SERVER['HTTP_VERIF_HASH']) ? $_SERVER['HTTP_VERIF_HASH'] : ''); - + // confirm the event's signature hash - if( $this->webhookHash !== $eventHash ) { - + if( $secretHash !== $eventHash ) + { $checked = false; - $this->httpStatusCode = 401; - $this->message = 'Transaction: Invalid event signature'; + $this->httpStatusCode = 400; + $this->message = 'Transaction: Invalid Flutterwave signature'; } - if($checked) { @@ -563,24 +575,21 @@ public function webhook() $this->httpStatusCode = 200; $this->setRawResponse($body); - $event = json_decode($body); + $response = json_decode($body); - if ('charge.completed' == ($event->event ?? '') ) { - $this->setAmount($event->data->amount); - $this->setEmail($event->data->customer->email); - $this->setReference($event->data->tx_ref); - $this->setResponse($event); - $this->setMessage($event->data->processor_response); + $this->setAmount($response->data->amount); + $this->setEmail($response->data->customer->email); + $this->setCurrency($response->data->currency); + $this->setReference($response->data->txRef); + $this->setResponse($response); - if ('successful' == $event->data->status) { - $this->status = true; - } + if( 'successful' == $response->data->status ) { + $this->status = true; + $this->setMessage('Transaction: Charge was completed', 200); } else { - $this->message = 'Transaction: Flutterwave charge.failed'; + $this->setMessage('Transaction: Charge ' . $response->data->status); } - } - } } \ No newline at end of file diff --git a/src/Processors/Paystack/Transaction.php b/src/Processors/Paystack/Transaction.php index 6385746..3822ff4 100644 --- a/src/Processors/Paystack/Transaction.php +++ b/src/Processors/Paystack/Transaction.php @@ -333,7 +333,7 @@ public function getReference(): string */ public function initialize(array $body = []) : void { - if( array_key_exists('amount', $body) ) { + if(array_key_exists('amount', $body) ) { $this->setAmount($body['amount']); } else { @@ -357,13 +357,31 @@ public function initialize(array $body = []) : void } } + if( array_key_exists('reference', $body) ) { + $this->setReference($body['reference']); + } + else { + if( !empty( $this->getReference() ) ) { + $body['reference'] = $this->getReference(); + } + } + if( array_key_exists('callback_url', $body) ) { $this->setRedirect($body['callback_url']); - $body['callback_url'] = $this->getRedirect(); } + else { + if( !empty( $this->getRedirect() ) ) { + $body['callback_url'] = $this->getRedirect(); + } + } + if( array_key_exists('currency', $body) ) { $this->setCurrency($body['currency']); - $body['currency'] = $this->getCurrency(); + } + else { + if( ! empty( $this->getCurrency() ) ) { + $body['currency'] = $this->getCurrency(); + } } $this->setBody($body); @@ -421,11 +439,11 @@ public function verify(string $reference = ''): void { $this->status = false; - if(empty($reference)) { + if( empty($reference) ) { $reference = $this->reference ?? ''; } - if(empty($reference)) { + if( empty($reference) ) { throw new PayException('Transaction: No reference supplied'); } @@ -434,9 +452,9 @@ public function verify(string $reference = ''): void ]); $request = $this->request; - $request->get(sprintf('%s/verify/%s', $this->endpoint, $reference)); + $request->get( sprintf('%s/verify/%s', $this->endpoint, $reference) ); - if($request->error) { + if( $request->error ) { $this->httpStatusCode = $request->errorCode; $this->setMessage(); } @@ -449,7 +467,8 @@ public function verify(string $reference = ''): void $this->httpStatusCode = $request->getHttpStatusCode(); - if('success' == $request->response->data->status) { + if( 'success' == $request->response->data->status ) + { $this->status = true; } diff --git a/tests/config.php b/tests/config.php index 0371de1..1b38236 100644 --- a/tests/config.php +++ b/tests/config.php @@ -2,4 +2,4 @@ define( 'PSTK_SECRET_KEY', 'sk_test_1cda807e053e0582d339ba491a3217f709b9ee04' ); -define( 'RAVE_SECRET_KEY', 'FLWSECK_TEST-0aad35c8d7be023695b631a59a530be8-X' ); \ No newline at end of file +define( 'RAVE_SECRET_KEY', 'FLWSECK_TEST-de0f78e22f8f4bbfe8a09852cefc7d9a-X' ); \ No newline at end of file diff --git a/tests/hook.txt b/tests/hook.txt deleted file mode 100644 index ebae458..0000000 --- a/tests/hook.txt +++ /dev/null @@ -1 +0,0 @@ -Thanks for making a payment via flutterwave \ No newline at end of file diff --git a/tests/index.php b/tests/index.php index 4b6a46f..5b5c8c1 100644 --- a/tests/index.php +++ b/tests/index.php @@ -4,21 +4,28 @@ require '../vendor/autoload.php'; require 'config.php'; -$processwith = new ProcessWith('flutterwave'); -$processwith->setSecretKey( RAVE_SECRET_KEY ); +$processwith = new ProcessWith('paystack'); +$processwith->setSecretKey( PSTK_SECRET_KEY ); $transaction = $processwith->transaction(); +$transaction->initialize([ + 'amount' => 1000, + 'email' => 'ikwuje@gmail.com', + 'callback_url' => 'http://localhost:3000/tests/verify.php', + 'currency' => 'NGN', +]); +/* Ravepay $transaction->initialize([ 'amount' => 1000, - 'email' => 'afuwapesunday12@gmail.com', - 'callback_url' => 'https://d47b4c1895d2.ngrok.io/tests/verify.php', + 'customer_email' => 'afuwapesunday12@gmail.com', + 'redirect_url' => 'http://localhost:3000/tests/verify.php', 'meta' => [ 'consumer_id' => 23, 'consumer_mac' => '92a3-912ba-1192a' ], -]); - +]); +*/ if( $transaction->status() ) { - file_put_contents('ref.txt', $transaction->getReference()); + file_put_contents('results/ref.txt', $transaction->getReference()); $transaction->checkout(); // redirect to the gateway checkout page } else { diff --git a/tests/ref.txt b/tests/ref.txt deleted file mode 100644 index 0f90c5c..0000000 --- a/tests/ref.txt +++ /dev/null @@ -1 +0,0 @@ -86f9c8d90f95d8 \ No newline at end of file diff --git a/tests/results/hook.txt b/tests/results/hook.txt new file mode 100644 index 0000000..f1c9ad4 --- /dev/null +++ b/tests/results/hook.txt @@ -0,0 +1 @@ +Webhook: Thanks for making a payment \ No newline at end of file diff --git a/tests/results/ref.txt b/tests/results/ref.txt new file mode 100644 index 0000000..22e0456 --- /dev/null +++ b/tests/results/ref.txt @@ -0,0 +1 @@ +lg207vl3tq \ No newline at end of file diff --git a/tests/results/verify.txt b/tests/results/verify.txt new file mode 100644 index 0000000..41ab9d4 --- /dev/null +++ b/tests/results/verify.txt @@ -0,0 +1 @@ +Verify: Thank you for making payment Via Flutterwave \ No newline at end of file diff --git a/tests/test.txt b/tests/test.txt deleted file mode 100644 index e69de29..0000000 diff --git a/tests/verify.php b/tests/verify.php index eb47f67..c035fc3 100644 --- a/tests/verify.php +++ b/tests/verify.php @@ -8,17 +8,20 @@ $amount = '1000'; $email = 'ikwuje@gmail.com'; -$processwith = new ProcessWith('flutterwave', RAVE_SECRET_KEY); +$processwith = new ProcessWith('paystack', PSTK_SECRET_KEY); $transaction = $processwith->transaction(); -$transaction->verify($_GET['transaction_id'] ?? ''); +$transaction->verify($_GET['reference'] ?? ''); + +header('Content-Type: application/json'); if ($transaction->status()) { + echo $transaction->getRawResponse(); + // give value // check email and amount before giving value if ( $amount == $transaction->getAmount() && $email == $transaction->getEmail() ) { - - file_put_contents( 'test.txt', 'Thank you for making payment Via Flutterwave' ); + file_put_contents( 'results/verify.txt', 'Verify: Thank you for making payment Via Flutterwave' ); echo 'Thank you for making payments'; } else { @@ -27,4 +30,6 @@ } else { echo $transaction->getMessage(); + + echo $transaction->getRawResponse(); } \ No newline at end of file diff --git a/tests/webhook.php b/tests/webhook.php index 2a27c38..5fe8503 100644 --- a/tests/webhook.php +++ b/tests/webhook.php @@ -5,28 +5,25 @@ require 'config.php'; $amount = '1000'; -$email = 'afuwapesunday12@gmail.com'; +$email = 'ikwuje@gmail.com'; -$processwith = new ProcessWith('flutterwave', RAVE_SECRET_KEY); +$processwith = new ProcessWith('paystack', PSTK_SECRET_KEY); $transaction = $processwith->transaction(); -$transaction->webhookHash('RAVE-SK-HASH'); $transaction->webhook(); -// file_put_contents( 'hook.txt', $transaction->webhook() ); - - +// // file_put_contents( 'hook.txt', $transaction->webhook() ); if ($transaction->status()) { // check the email and the amount // before giving value if ( $amount == $transaction->getAmount() && $email == $transaction->getEmail() ) { - file_put_contents( 'hook.txt', 'Thanks for making a payment via flutterwave' ); + file_put_contents( 'results/hook.txt', 'Webhook: Thanks for making a payment' ); } else { - file_put_contents( 'hook.txt', 'Amount does not match via flutterwave' ); + file_put_contents( 'results/hook.txt', 'Webhook: Amount does not match' ); } } else { - file_put_contents( 'hook.txt', $transaction->getMessage() ); + file_put_contents( 'results/hook.txt', $transaction->getMessage() ); } \ No newline at end of file