Skip to content

Commit e9e553e

Browse files
committed
Add webhook parsing support
1 parent 4628a09 commit e9e553e

8 files changed

+567
-1
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
},
3535
"require-dev": {
3636
"omnipay/tests": "~3.0",
37-
"squizlabs/php_codesniffer": "^3.5"
37+
"squizlabs/php_codesniffer": "^3.5",
38+
"symfony/psr-http-message-bridge": "^2.0"
3839
},
3940
"extra": {
4041
"branch-alias": {

src/Message/WebhookNotification.php

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?php
2+
3+
namespace Omnipay\BPOINT\Message;
4+
5+
use Omnipay\Common\Http\ClientInterface;
6+
use Omnipay\Common\Message\AbstractRequest;
7+
use Omnipay\Common\Message\NotificationInterface;
8+
use Omnipay\Common\Message\RequestInterface;
9+
use Omnipay\Common\Message\ResponseInterface;
10+
use Symfony\Component\HttpFoundation\Request as HttpRequest;
11+
12+
/**
13+
* Accept an incoming notification (a webhook)
14+
*
15+
* @see https://www.bpoint.com.au/developers/v3/#!#webhooks
16+
*/
17+
class WebhookNotification extends AbstractRequest implements NotificationInterface, ResponseInterface
18+
{
19+
/**
20+
* @inheritDoc
21+
*/
22+
public function __construct(ClientInterface $httpClient, HttpRequest $httpRequest)
23+
{
24+
parent::__construct($httpClient, $httpRequest);
25+
// fetch POST stream directly
26+
$this->data = json_decode($httpRequest->getContent(), true);
27+
}
28+
29+
/**
30+
* ResponseInterface implemented so that we can return self here for any legacy support that uses send()
31+
*/
32+
public function sendData($data)
33+
{
34+
return $this;
35+
}
36+
37+
/**
38+
* Get the authorisation code if available.
39+
*
40+
* @return null|string
41+
*/
42+
public function getTransactionReference()
43+
{
44+
return isset($this->data['AuthoriseId']) ? $this->data['AuthoriseId'] : null;
45+
}
46+
47+
/**
48+
* Was the transaction successful?
49+
*
50+
* @return string Transaction status, one of {@link NotificationInterface::STATUS_COMPLETED},
51+
* {@link NotificationInterface::STATUS_PENDING}, or {@link NotificationInterface::STATUS_FAILED}.
52+
*/
53+
public function getTransactionStatus()
54+
{
55+
if (!isset($this->data['ResponseCode'])) {
56+
return NotificationInterface::STATUS_FAILED;
57+
}
58+
if ($this->data['ResponseCode'] == '0') {
59+
return NotificationInterface::STATUS_COMPLETED;
60+
}
61+
if ($this->data['ResponseCode'] == 'P') {
62+
return NotificationInterface::STATUS_PENDING;
63+
}
64+
65+
// last resort, assume failure
66+
return NotificationInterface::STATUS_FAILED;
67+
}
68+
69+
/**
70+
* Get the merchant response message if available.
71+
*
72+
* @return null|string
73+
*/
74+
public function getMessage()
75+
{
76+
return isset($this->data['ResponseText']) ? $this->data['ResponseText'] : null;
77+
}
78+
79+
public function getData()
80+
{
81+
return $this->data;
82+
}
83+
84+
/**
85+
* Get the original request which generated this response
86+
*
87+
* @return RequestInterface
88+
*/
89+
public function getRequest()
90+
{
91+
return $this;
92+
}
93+
94+
/**
95+
* Is the response successful?
96+
*
97+
* @return boolean
98+
*/
99+
public function isSuccessful()
100+
{
101+
return $this->getTransactionStatus() == NotificationInterface::STATUS_COMPLETED;
102+
}
103+
104+
/**
105+
* Does the response require a redirect?
106+
*
107+
* @return boolean
108+
*/
109+
public function isRedirect()
110+
{
111+
return false;
112+
}
113+
114+
/**
115+
* Is the transaction cancelled by the user?
116+
*
117+
* @return boolean
118+
*/
119+
public function isCancelled()
120+
{
121+
return isset($this->data['ResponseCode']) && $this->data['ResponseCode'] == 'C';
122+
}
123+
124+
/**
125+
* Response code
126+
*
127+
* @return null|string A response code from the payment gateway
128+
*/
129+
public function getCode()
130+
{
131+
return isset($this->data['ResponseCode']) ? $this->data['ResponseCode'] : null;
132+
}
133+
134+
/**
135+
* Get the card type if available.
136+
*
137+
* @return null|string
138+
*/
139+
public function getCardType()
140+
{
141+
return isset($this->data['CardType']) ? $this->data['CardType'] : null;
142+
}
143+
}

src/RedirectGateway.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Omnipay\Common\AbstractGateway;
66
use Omnipay\BPOINT\Message\CompletePurchaseRequest;
77
use Omnipay\BPOINT\Message\PurchaseRequest;
8+
use Omnipay\BPOINT\Message\WebhookNotification;
89

910
/**
1011
* BPOINT Redirect Gateway
@@ -78,4 +79,9 @@ public function completePurchase(array $parameters = array())
7879
{
7980
return $this->createRequest('\Omnipay\BPOINT\Message\CompletePurchaseRequest', $parameters);
8081
}
82+
83+
public function acceptNotification()
84+
{
85+
return $this->createRequest('\Omnipay\BPOINT\Message\WebhookNotification', array());
86+
}
8187
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
POST http://yourmerchantwebsite.com/txnWebHook HTTP/1.1
2+
Content-Type: application/json; charset=utf-8
3+
Host: merchant.com
4+
Content-Length: 827
5+
Expect: 100-continue
6+
Proxy-Connection: Keep-Alive
7+
8+
{
9+
"Action" : "payment",
10+
"Amount" : 19900,
11+
"AmountOriginal" : 19800,
12+
"AmountSurcharge" : 100,
13+
"AuthoriseId" : "",
14+
"BankAccountDetails" : {
15+
"AccountName" : "",
16+
"AccountNumber" : "",
17+
"BSBNumber" : "",
18+
"TruncatedAccountNumber" : ""
19+
},
20+
"BankResponseCode" : "",
21+
"BillerCode" : "",
22+
"CardDetails" : {
23+
"CardHolderName" : "John Smith",
24+
"Category" : "",
25+
"ExpiryDate" : "0521",
26+
"Issuer" : "",
27+
"IssuerCountryCode" : "",
28+
"Localisation" : "",
29+
"MaskedCardNumber" : "512345...346",
30+
"SubType" : "extra comma here causes a malformed JSON error",
31+
},
32+
"CardType" : "",
33+
"Crn1" : "Test reference 1",
34+
"Crn2" : "",
35+
"Crn3" : "",
36+
"Currency" : "AUD",
37+
"CVNResult" : {
38+
"CVNResultCode" : ""
39+
},
40+
"DVToken" : "",
41+
"EmailAddress" : "john.smith@email.com",
42+
"FraudScreeningResponse" : {
43+
"ReDResponse" : {
44+
"FRAUD_REC_ID" : "",
45+
"FRAUD_RSP_CD" : "",
46+
"FRAUD_STAT_CD" : "",
47+
"ORD_ID" : "",
48+
"REQ_ID" : "",
49+
"STAT_CD" : ""
50+
},
51+
"ResponseCode" : "",
52+
"ResponseMessage" : "",
53+
"TxnRejected" : false
54+
},
55+
"IsCVNPresent" : false,
56+
"IsTestTxn" : false,
57+
"IsThreeDS" : false,
58+
"MerchantNumber" : "",
59+
"MerchantReference" : "Test merchant reference",
60+
"OriginalTxnNumber" : "",
61+
"ProcessedDateTime" : "",
62+
"ReceiptNumber" : "",
63+
"ResponseCode" : "",
64+
"ResponseText" : "",
65+
"RRN" : "",
66+
"SettlementDate" : "",
67+
"Source" : "",
68+
"StoreCard" : false,
69+
"SubType" : "single",
70+
"ThreeDSResponse" : {
71+
"Eci" : "",
72+
"Enrolled" : "",
73+
"Status" : "",
74+
"VerifySecurityLevel" : "",
75+
"VerifyStatus" : "",
76+
"VerifyToken" : "",
77+
"VerifyType" : "",
78+
"XID" : ""
79+
},
80+
"TxnNumber" : "",
81+
"Type" : "internet",
82+
"StatementDescriptor" : {
83+
"AddressLine1" : "",
84+
"AddressLine2" : "",
85+
"City" : "",
86+
"CompanyName" : "",
87+
"CountryCode" : "",
88+
"Postcode" : "",
89+
"State" : "",
90+
"MerchantName" : "",
91+
"PhoneNumber" : ""
92+
}
93+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
POST http://yourmerchantwebsite.com/txnWebHook HTTP/1.1
2+
Content-Type: application/json; charset=utf-8
3+
Content-Length: 827
4+
Expect: 100-continue
5+
Proxy-Connection: Keep-Alive
6+
7+
{
8+
"Action" : "payment",
9+
"Amount" : 19900,
10+
"AmountOriginal" : 19800,
11+
"AmountSurcharge" : 100,
12+
"AuthoriseId" : "372627",
13+
"BankAccountDetails" : null,
14+
"BankResponseCode" : "00",
15+
"BillerCode" : null,
16+
"CardDetails" : {
17+
"CardHolderName" : "John Smith",
18+
"Category" : "STANDARD",
19+
"ExpiryDate" : "0521",
20+
"Issuer" : "BANCO DEL PICHINCHA, C.A.",
21+
"IssuerCountryCode" : "ECU",
22+
"Localisation" : "international",
23+
"MaskedCardNumber" : "512345...346",
24+
"SubType" : "credit"
25+
},
26+
"CardType" : "MC",
27+
"Crn1" : "test crn1",
28+
"Crn2" : "test crn2",
29+
"Crn3" : "test crn3",
30+
"Currency" : "AUD",
31+
"CVNResult" : {
32+
"CVNResultCode" : "M"
33+
},
34+
"DVToken" : null,
35+
"EmailAddress" : null,
36+
"FraudScreeningResponse" : {
37+
"ReDResponse" : null,
38+
"ResponseCode" : "",
39+
"ResponseMessage" : "",
40+
"TxnRejected" : false
41+
},
42+
"IsCVNPresent" : true,
43+
"IsTestTxn" : true,
44+
"IsThreeDS" : false,
45+
"MerchantNumber" : "5353109000000000",
46+
"MerchantReference" : "test merchant ref",
47+
"OriginalTxnNumber" : null,
48+
"ProcessedDateTime" : "2014-12-12T12:15:19.6370000",
49+
"ReceiptNumber" : "49316411177",
50+
"ResponseCode" : "6",
51+
"ResponseText" : "Transaction Declined",
52+
"RRN" : "434612372626",
53+
"SettlementDate" : "20141212",
54+
"Source" : "internet",
55+
"StoreCard" : false,
56+
"SubType" : "single",
57+
"ThreeDSResponse" : null,
58+
"TxnNumber" : "1177",
59+
"Type" : "internet",
60+
"StatementDescriptor" : {
61+
"AddressLine1" : "123 Drive Street",
62+
"AddressLine2" : "",
63+
"City" : "Melbourne",
64+
"CompanyName" : "A Company Name",
65+
"CountryCode" : "AUS",
66+
"Postcode" : "3000",
67+
"State" : "Victoria",
68+
"MerchantName" : "A Merchant Name",
69+
"PhoneNumber" : "0123456789"
70+
}
71+
}

0 commit comments

Comments
 (0)