33/**
44 * Paystack Magento2 Module using \Magento\Payment\Model\Method\AbstractMethod
55 * Copyright (C) 2019 Paystack.com
6- *
6+ *
77 * This file is part of Pstk/Paystack.
8- *
8+ *
99 * Pstk/Paystack is free software => you can redistribute it and/or modify
1010 * it under the terms of the GNU General Public License as published by
1111 * the Free Software Foundation, either version 3 of the License, or
1212 * (at your option) any later version.
13- *
13+ *
1414 * This program is distributed in the hope that it will be useful,
1515 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1616 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1717 * GNU General Public License for more details.
18- *
18+ *
1919 * You should have received a copy of the GNU General Public License
2020 * along with this program. If not, see <http =>//www.gnu.org/licenses/>.
2121 */
2222
2323namespace Pstk \Paystack \Controller \Payment ;
2424
25-
26- use Magento \Sales \Model \Order ;
27-
2825class Webhook extends AbstractPaystackStandard
2926{
3027
3128 public function execute () {
3229 $ finalMessage = "failed " ;
33-
30+
3431 $ resultFactory = $ this ->resultFactory ->create (\Magento \Framework \Controller \ResultFactory::TYPE_RAW );
3532 try {
3633
3734 // Retrieve the request's body and parse it as JSON
38- $ event = \ Yabacon \ Paystack \Event:: capture ();
35+ $ rawBody = $ this -> request -> getContent ();
3936 http_response_code (200 );
40-
41- /* It is a important to log all events received. Add code *
42- * here to log the signature and body to db or file */
43- $ this ->logger ->debug ("PAYSTACK_LOG: {$ event ->raw }" );
4437
45- /* Verify that the signature matches one of your keys */
46- $ secretKey = $ this ->configProvider ->getSecretKeyArray ();
47- $ owner = $ event ->discoverOwner ($ secretKey );
38+ $ this ->logger ->info ("Paystack Webhook: received request " );
4839
49- if (!$ owner ) {
50- // None of the keys matched the event's signature
40+ // Validate webhook signature
41+ $ signature = $ this ->request ->getHeader ('X-Paystack-Signature ' ) ?: '' ;
42+ if (!$ signature || !$ this ->paystackClient ->validateWebhookSignature ($ rawBody , $ signature )) {
43+ $ this ->logger ->warning ("Paystack Webhook: signature validation failed " );
5144 $ resultFactory ->setContents ("auth failed " );
5245 return $ resultFactory ;
5346 }
5447
55- // Do something with $event->obj
56- // Give value to your customer but don't give any output
57- // Remember that this is a call from Paystack's servers and
58- // Your customer is not seeing the response here at all
59- switch ($ event ->obj ->event ) {
60- // charge.success
61- case 'charge.success ' :
62- if ('success ' === $ event ->obj ->data ->status ) {
63- $ transactionDetails = $ this ->paystack ->transaction ->verify ([
64- 'reference ' => $ event ->obj ->data ->reference
65- ]);
48+ $ this ->logger ->info ("Paystack Webhook: signature valid " );
6649
67- $ reference = $ transactionDetails ->data ->reference ;
50+ $ event = json_decode ($ rawBody );
51+ if (!$ event ) {
52+ $ resultFactory ->setContents ("invalid payload " );
53+ return $ resultFactory ;
54+ }
6855
69- $ order = $ this ->orderInterface ->loadByIncrementId ($ reference );
56+ $ this ->logger ->info ("Paystack Webhook: event type = " . ($ event ->event ?? 'unknown ' ));
57+
58+ switch ($ event ->event ) {
59+ case 'charge.success ' :
60+ if ('success ' === $ event ->data ->status ) {
61+ $ transactionDetails = $ this ->paystackClient ->verifyTransaction ($ event ->data ->reference );
7062
71- //if is popup mode, reference is generated by Paystack and we provided quoteId instead
72- if ((! $ order || ! $ order -> getId ()) && isset ( $ event -> obj -> data -> metadata -> quoteId )){
63+ $ reference = $ transactionDetails -> data -> reference ;
64+ $ this -> logger -> info ( " Paystack Webhook: verified transaction " , [ ' reference ' => $ reference ]);
7365
66+ $ this ->paystackClient ->logTransactionSuccess ($ reference , $ this ->configProvider ->getPublicKey ());
7467
75- $ reference = $ transactionDetails ->data ->reference ;
76- //PSTK_LOGGER HERE
77- log_transaction_success ($ reference );
78- //------------------------
79- $ order = $ this ->orderInterface ->loadByIncrementId ($ reference );
80-
81- //if is popup mode, reference is generated by Paystack and we provided quoteId instead
82- if ((!$ order || !$ order ->getId ()) && isset ($ event ->obj ->data ->metadata ->quoteId )){
83-
84- $ objectManager = \Magento \Framework \App \ObjectManager::getInstance ();
85- $ searchCriteriaBuilder = $ objectManager ->create ('Magento\Framework\Api\SearchCriteriaBuilder ' );
86- $ searchCriteria = $ searchCriteriaBuilder ->addFilter ('quote_id ' , $ event ->obj ->data ->metadata ->quoteId , 'eq ' )->create ();
87- $ items = $ this ->orderRepository ->getList ($ searchCriteria );
88- if ($ items ->getTotalCount () == 1 ){
89- $ order = $ items ->getFirstItem ();
68+ $ order = $ this ->orderInterface ->loadByIncrementId ($ reference );
9069
91- }
70+ // In popup mode, reference is generated by Paystack and we provided quoteId instead
71+ if ((!$ order || !$ order ->getId ()) && isset ($ event ->data ->metadata ->quoteId )) {
72+ $ this ->logger ->info ("Paystack Webhook: order not found by reference, searching by quoteId " , ['quoteId ' => $ event ->data ->metadata ->quoteId ]);
73+ $ objectManager = \Magento \Framework \App \ObjectManager::getInstance ();
74+ $ searchCriteriaBuilder = $ objectManager ->create ('Magento\Framework\Api\SearchCriteriaBuilder ' );
75+ $ searchCriteria = $ searchCriteriaBuilder ->addFilter ('quote_id ' , $ event ->data ->metadata ->quoteId , 'eq ' )->create ();
76+ $ items = $ this ->orderRepository ->getList ($ searchCriteria );
77+ if ($ items ->getTotalCount () == 1 ) {
78+ $ order = $ items ->getFirstItem ();
79+ }
80+ }
9281
9382 if ($ order && $ order ->getId ()) {
83+ $ this ->logger ->info ("Paystack Webhook: order found, dispatching verify event " , [
84+ 'order_id ' => $ order ->getIncrementId (),
85+ 'current_status ' => $ order ->getStatus (),
86+ ]);
9487 // dispatch the `payment_verify_after` event to update the order status
9588 $ this ->eventManager ->dispatch ('paystack_payment_verify_after ' , [
9689 "paystack_order " => $ order ,
@@ -99,43 +92,16 @@ public function execute() {
9992 $ resultFactory ->setContents ("success " );
10093 return $ resultFactory ;
10194 }
95+ $ this ->logger ->warning ("Paystack Webhook: order not found for reference " . $ reference );
10296 }
103- }
10497 break ;
10598 }
106- }
107- } catch ( Exception $ exc) {
99+ } catch ( \ Exception $ exc ) {
100+ $ this -> logger -> error ( " Paystack Webhook: exception " , [ ' error ' => $ exc-> getMessage ()]);
108101 $ finalMessage = $ exc ->getMessage ();
109102 }
110-
103+
111104 $ resultFactory ->setContents ($ finalMessage );
112105 return $ resultFactory ;
113106 }
114-
115- function log_transaction_success ($ trx_ref ){
116- //send reference to logger along with plugin name and public key
117- $ url = "https://plugin-tracker.paystackintegrations.com/log/charge_success " ;
118- $ plugin_name = 'magento-2 ' ;
119- $ public_key = $ this ->configProvider ->getPublicKey ();
120-
121- $ fields = [
122- 'plugin_name ' => $ plugin_name ,
123- 'transaction_reference ' => $ trx_ref ,
124- 'public_key ' => $ public_key
125- ];
126-
127- $ fields_string = http_build_query ($ fields );
128-
129- $ ch = curl_init ();
130-
131- curl_setopt ($ ch ,CURLOPT_URL , $ url );
132- curl_setopt ($ ch ,CURLOPT_POST , true );
133- curl_setopt ($ ch ,CURLOPT_POSTFIELDS , $ fields_string );
134-
135- curl_setopt ($ ch ,CURLOPT_RETURNTRANSFER , true );
136-
137- //execute post
138- $ result = curl_exec ($ ch );
139- // echo $result;
140- }
141107}
0 commit comments