1: <?php
2:
3: namespace mcfedr\Paypal\Notifications;
4:
5: use mcfedr\Paypal\Authentication;
6: use mcfedr\Paypal\Exceptions\NotificationBusinessInvalidException;
7: use mcfedr\Paypal\Exceptions\NotificationCurrencyInvalidException;
8: use mcfedr\Paypal\Settings;
9:
10: /**
11: * Describes a notification
12: */
13: abstract class Notification {
14:
15: /**
16: * Type of notification
17: *
18: * @see REFUND
19: * @see CART
20: * @see MASSPAY
21: * @see SUBSCRIPTION
22: * @see ADAPTIVE
23: * @var string
24: */
25: public $type;
26:
27: /**
28: * type for refund notification
29: */
30: const REFUND = 'refund';
31:
32: /**
33: * type for cart notification
34: */
35: const CART = 'cart';
36:
37: /**
38: * type for masspay notification
39: */
40: const MASSPAY = 'masspay';
41:
42: /**
43: * type for masspay notification
44: */
45: const MASSPAYS = 'masspays';
46:
47: /**
48: * type for subscription notifications
49: */
50: const SUBSCRIPTION = 'subscription';
51:
52: const ADAPTIVE = 'adaptive';
53:
54: /**
55: * Type of transaction (paypal)
56: * @see TXT_CART
57: * @see TXT_WEB_ACCEPT
58: * @see TXT_MASSPAY
59: * @see TXT_SUBSCRIPTION_START
60: * @see TXT_SUBSCRIPTION_PAYMENT
61: * @see TXT_SUBSCRIPTION_MODIFY
62: * @see TXT_SUBSCRIPTION_FAILED
63: * @see TXT_SUBSCRIPTION_EXPIRE
64: * @see TXT_SUBSCRIPTION_CANCEL
65: * @see TXT_ADAPTIVE_CREATE
66: * @see TXT_ADAPTIVE_ADJUSTMENT
67: * @var string
68: */
69: public $transactionType;
70:
71: const TXT_CART = 'cart';
72: const TXT_WEB_ACCEPT = 'web_accept';
73: const TXT_MASSPAY = 'masspay';
74: const TXT_SUBSCRIPTION_START = 'subscr_signup';
75: const TXT_SUBSCRIPTION_PAYMENT = 'subscr_payment';
76: const TXT_SUBSCRIPTION_MODIFY = 'subscr_modify';
77: const TXT_SUBSCRIPTION_FAILED = 'subscr_failed';
78: const TXT_SUBSCRIPTION_EXPIRE = 'subscr_eot';
79: const TXT_SUBSCRIPTION_CANCEL = 'subscr_cancel';
80: const TXT_ADAPTIVE_CREATE = 'Adaptive Payment PAY';
81: const TXT_ADAPTIVE_ADJUSTMENT = 'Adjustment';
82:
83: /**
84: * Paypals id for this transaction
85: * @var string
86: */
87: public $transactionId;
88:
89: /**
90: * The original transaction (for refunds)
91: * @var string
92: */
93: public $parentTransactionId;
94:
95: /**
96: * The invoice id you sent as part of this transaction
97: * @var int
98: */
99: public $invoiceId;
100:
101: /**
102: * The custom data you sent
103: * @var string
104: */
105: public $custom;
106:
107: /**
108: * The total amount paid
109: * You should check this is what you expect it to be
110: * @var double
111: */
112: public $total;
113:
114: /**
115: * The amount paid minus shipping and handling
116: * @var double
117: */
118: public $amount;
119:
120: /**
121: * Currency paid in
122: * @var string
123: */
124: public $currency;
125:
126: /**
127: * The paypal fee (you received {@link $amount}-{@link $fee})
128: * @var double
129: */
130: public $fee;
131:
132: /**
133: * Who was paid
134: * @var string
135: */
136: public $business;
137:
138: /**
139: * Status of payment
140: * The status of the payment:
141: * <b>Canceled_Reversal:</b> A reversal has been canceled. For example, you
142: * won a dispute with the customer, and the funds for the transaction
143: * that was reversed have been returned to you.
144: * <b>Completed:</b> The payment has been completed,
145: * and the funds have been added successfully to your account balance.
146: * <b>Created:</b> A German ELV payment is made using Express Checkout.
147: * <b>Denied:</b> You denied the payment.
148: * This happens only if the payment was previously pending because of
149: * possible reasons described for the pending_reason variable
150: * or the Fraud_Management_Filters_x variable.
151: * <b>Expired:</b> This authorization has expired and cannot be captured.
152: * <b>Failed:</b> The payment has failed.
153: * This happens only if the payment was made from your
154: * customer’s bank account.
155: * <b>Pending:</b> The payment is pending. See pending_reason for more information.
156: * <b>Refunded:</b> You refunded the payment.
157: * <b>Reversed:</b> A payment was reversed due to a chargeback or other type of
158: * reversal. The funds have been removed from your account balance
159: * and returned to the buyer. The reason for the reversal is
160: * specified in the ReasonCode element.
161: * <b>Processed:</b> A payment has been accepted.
162: * <b>Voided:</b> This authorization has been voided.
163: * @var string
164: */
165: public $status;
166:
167: /**
168: * Time the payment was made
169: * @var \DateTime
170: */
171: public $date;
172:
173: /**
174: * Has this notification been sent before
175: * @var bool
176: */
177: public $resent;
178:
179: /**
180: * Is this a sandbox notification
181: * @var bool
182: */
183: public $sandbox;
184:
185: public function __construct($vars) {
186: if (isset($vars['txn_type'])) {
187: $this->transactionType = $vars['txn_type'];
188: }
189:
190: if (isset($vars['txn_id'])) {
191: $this->transactionId = $vars['txn_id'];
192: }
193:
194: if (isset($vars['parent_txn_id'])) {
195: $this->parentTransactionId = $vars['parent_txn_id'];
196: }
197:
198: if (isset($vars['invoice'])) {
199: $this->invoiceId = $vars['invoice'];
200: }
201:
202: if (isset($vars['custom'])) {
203: $this->custom = $vars['custom'];
204: }
205:
206: if (isset($vars['payment_status'])) {
207: $this->status = $vars['payment_status'];
208: }
209:
210: if (isset($vars['pending_reason'])) {
211: $this->pendingReason = $vars['pending_reason'];
212: }
213:
214: if (isset($vars['payment_date'])) {
215: $this->date = new \DateTime($vars['payment_date']);
216: }
217:
218: $this->resent = isset($vars['resend']) && $vars['resend'] == 'true';
219: $this->sandbox = isset($vars['test_ipn']) && $vars['test_ipn'] == 1;
220: }
221:
222: /**
223: * Check everything is as expected
224: *
225: * @param Authentication $authentication
226: * @param Settings $settings
227: * @return bool
228: */
229: public function isOK(Authentication $authentication, Settings $settings) {
230: return $this->isBusinessCorrect($authentication) && $this->isCurrencyCorrect($settings);
231: }
232:
233: /**
234: * Check that the notification matches the expected business
235: *
236: * @param Authentication $authentication
237: * @throws NotificationBusinessInvalidException
238: * @return bool
239: */
240: protected function isBusinessCorrect(Authentication $authentication) {
241: if ($this->business != $authentication->getEmail() || $this->sandbox != $authentication->isSandbox()) {
242: throw new NotificationBusinessInvalidException($this);
243: }
244: return true;
245: }
246:
247: /**
248: * Check the correct currency was used
249: *
250: * @param Settings $settings
251: * @throws NotificationCurrencyInvalidException
252: * @return bool
253: */
254: protected function isCurrencyCorrect(Settings $settings) {
255: if ($this->currency != $settings->currency) {
256: throw new NotificationCurrencyInvalidException($this, $this->currency, $settings->currency);
257: }
258: return true;
259: }
260:
261: }
262: