55
66use Bitpay \BPCheckout \Api \IpnManagementInterface ;
77use Bitpay \BPCheckout \Exception \IPNValidationException ;
8+ use Bitpay \BPCheckout \Exception \HMACVerificationException ;
89use Bitpay \BPCheckout \Helper \ReturnHash ;
910use Bitpay \BPCheckout \Logger \Logger ;
1011use Bitpay \BPCheckout \Model \Ipn \BPCItem ;
1112use Bitpay \BPCheckout \Model \Ipn \Validator ;
13+ use Bitpay \BPCheckout \Model \Ipn \WebhookVerifier ;
1214use Magento \Checkout \Model \Session ;
1315use Magento \Framework \App \ResponseFactory ;
1416use Magento \Framework \DataObject ;
17+ use Magento \Framework \Encryption \EncryptorInterface ;
1518use Magento \Framework \Registry ;
1619use Magento \Framework \Serialize \Serializer \Json ;
1720use Magento \Framework \UrlInterface ;
1821use Magento \Framework \Webapi \Rest \Request ;
1922use Magento \Framework \Webapi \Rest \Response ;
2023use Magento \Quote \Model \QuoteFactory ;
21- use Magento \Sales \Api \ Data \ OrderInterface ;
24+ use Magento \Sales \Model \ OrderFactory ;
2225
2326/**
2427 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -32,7 +35,7 @@ class IpnManagement implements IpnManagementInterface
3235 protected UrlInterface $ url ;
3336 protected Session $ checkoutSession ;
3437 protected QuoteFactory $ quoteFactory ;
35- protected OrderInterface $ orderInterface ;
38+ protected OrderFactory $ orderFactory ;
3639 protected Registry $ coreRegistry ;
3740 protected Logger $ logger ;
3841 protected Config $ config ;
@@ -42,14 +45,33 @@ class IpnManagement implements IpnManagementInterface
4245 protected Request $ request ;
4346 protected Client $ client ;
4447 protected Response $ response ;
48+
49+ /**
50+ * @var BitpayInvoiceRepository
51+ */
52+ protected BitpayInvoiceRepository $ bitpayInvoiceRepository ;
53+
54+ /**
55+ * @var EncryptorInterface
56+ */
57+ protected EncryptorInterface $ encryptor ;
58+
59+ /**
60+ * @var WebhookVerifier
61+ */
62+ protected WebhookVerifier $ webhookVerifier ;
63+
64+ /**
65+ * @var ReturnHash
66+ */
4567 protected ReturnHash $ returnHashHelper ;
4668
4769 /**
4870 * @param ResponseFactory $responseFactory
4971 * @param UrlInterface $url
5072 * @param Registry $registry
5173 * @param Session $checkoutSession
52- * @param OrderInterface $orderInterface
74+ * @param OrderFactory $orderFactory
5375 * @param QuoteFactory $quoteFactory
5476 * @param Logger $logger
5577 * @param Config $config
@@ -59,6 +81,9 @@ class IpnManagement implements IpnManagementInterface
5981 * @param Request $request
6082 * @param Client $client
6183 * @param Response $response
84+ * @param BitpayInvoiceRepository $bitpayInvoiceRepository
85+ * @param EncryptorInterface $encryptor
86+ * @param WebhookVerifier $webhookVerifier
6287 * @param ReturnHash $returnHashHelper
6388 * @SuppressWarnings(PHPMD.ExcessiveParameterList)
6489 */
@@ -67,7 +92,7 @@ public function __construct(
6792 UrlInterface $ url ,
6893 Registry $ registry ,
6994 Session $ checkoutSession ,
70- OrderInterface $ orderInterface ,
95+ OrderFactory $ orderFactory ,
7196 QuoteFactory $ quoteFactory ,
7297 Logger $ logger ,
7398 Config $ config ,
@@ -77,13 +102,16 @@ public function __construct(
77102 Request $ request ,
78103 Client $ client ,
79104 Response $ response ,
105+ BitpayInvoiceRepository $ bitpayInvoiceRepository ,
106+ EncryptorInterface $ encryptor ,
107+ WebhookVerifier $ webhookVerifier ,
80108 ReturnHash $ returnHashHelper
81109 ) {
82110 $ this ->coreRegistry = $ registry ;
83111 $ this ->responseFactory = $ responseFactory ;
84112 $ this ->url = $ url ;
85113 $ this ->quoteFactory = $ quoteFactory ;
86- $ this ->orderInterface = $ orderInterface ;
114+ $ this ->orderFactory = $ orderFactory ;
87115 $ this ->checkoutSession = $ checkoutSession ;
88116 $ this ->logger = $ logger ;
89117 $ this ->config = $ config ;
@@ -93,6 +121,9 @@ public function __construct(
93121 $ this ->request = $ request ;
94122 $ this ->client = $ client ;
95123 $ this ->response = $ response ;
124+ $ this ->bitpayInvoiceRepository = $ bitpayInvoiceRepository ;
125+ $ this ->encryptor = $ encryptor ;
126+ $ this ->webhookVerifier = $ webhookVerifier ;
96127 $ this ->returnHashHelper = $ returnHashHelper ;
97128 }
98129
@@ -108,7 +139,7 @@ public function postClose()
108139 $ response = $ this ->responseFactory ->create ();
109140 try {
110141 $ orderID = $ this ->request ->getParam ('orderID ' , null );
111- $ order = $ this ->orderInterface ->loadByIncrementId ($ orderID );
142+ $ order = $ this ->orderFactory -> create () ->loadByIncrementId ($ orderID );
112143 $ invoiceCloseHandling = $ this ->config ->getBitpayInvoiceCloseHandling ();
113144 if ($ this ->config ->getBitpayCheckoutSuccess () === 'standard ' && $ invoiceCloseHandling === 'keep_order ' ) {
114145 $ this ->checkoutSession ->setLastSuccessQuoteId ($ order ->getQuoteId ())
@@ -151,10 +182,22 @@ public function postClose()
151182 public function postIpn ()
152183 {
153184 try {
154- $ allData = $ this ->serializer ->unserialize ($ this ->request ->getContent ());
185+ $ requestBody = $ this ->request ->getContent ();
186+ $ allData = $ this ->serializer ->unserialize ($ requestBody );
155187 $ data = $ allData ['data ' ];
156188 $ event = $ allData ['event ' ];
157189 $ orderId = $ data ['orderId ' ];
190+
191+ $ bitPayInvoiceData = $ this ->bitpayInvoiceRepository ->getByOrderId ($ orderId );
192+ if (!empty ($ bitPayInvoiceData ['bitpay_token ' ])) {
193+ $ signingKey = $ this ->encryptor ->decrypt ($ bitPayInvoiceData ['bitpay_token ' ]);
194+ $ xSignature = $ this ->request ->getHeader ('x-signature ' );
195+
196+ if (!$ this ->webhookVerifier ->isValidHmac ($ signingKey , $ xSignature , $ requestBody )) {
197+ throw new HMACVerificationException ('HMAC Verification Failed! ' );
198+ }
199+ }
200+
158201 $ orderInvoiceId = $ data ['id ' ];
159202 $ row = $ this ->transactionRepository ->findBy ($ orderId , $ orderInvoiceId );
160203 $ client = $ this ->client ->initialize ();
@@ -179,7 +222,7 @@ public function postIpn()
179222 $ invoiceStatus = $ this ->invoice ->getBPCCheckInvoiceStatus ($ client , $ orderInvoiceId );
180223 $ updateWhere = ['order_id = ? ' => $ orderId , 'transaction_id = ? ' => $ orderInvoiceId ];
181224 $ this ->transactionRepository ->update ('transaction_status ' , $ invoiceStatus , $ updateWhere );
182- $ order = $ this ->orderInterface ->loadByIncrementId ($ orderId );
225+ $ order = $ this ->orderFactory -> create () ->loadByIncrementId ($ orderId );
183226 switch ($ event ['name ' ]) {
184227 case Invoice::COMPLETED :
185228 if ($ invoiceStatus == 'complete ' ) {
0 commit comments