PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.31.1
GiveWP – Donation Plugin and Fundraising Platform v2.31.1
4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / src / LegacyPaymentGateways / Adapters / LegacyPaymentGatewayAdapter.php
give / src / LegacyPaymentGateways / Adapters Last commit date
LegacyPaymentGatewayAdapter.php 3 years ago
LegacyPaymentGatewayAdapter.php
344 lines
1 <?php
2
3 namespace Give\LegacyPaymentGateways\Adapters;
4
5 use Exception;
6 use Give\Donations\Models\Donation;
7 use Give\Donations\ValueObjects\DonationType;
8 use Give\Donors\Models\Donor;
9 use Give\Framework\PaymentGateways\Contracts\PaymentGatewayInterface;
10 use Give\Framework\PaymentGateways\Controllers\GatewayPaymentController;
11 use Give\Framework\PaymentGateways\Controllers\GatewaySubscriptionController;
12 use Give\Framework\PaymentGateways\PaymentGateway;
13 use Give\Helpers\Form\Utils;
14 use Give\PaymentGateways\Actions\GetGatewayDataFromRequest;
15 use Give\PaymentGateways\DataTransferObjects\FormData;
16 use Give\PaymentGateways\DataTransferObjects\SubscriptionData;
17 use Give\Session\SessionDonation\DonationAccessor;
18 use Give\Subscriptions\Models\Subscription;
19 use Give\Subscriptions\ValueObjects\SubscriptionMode;
20 use Give\Subscriptions\ValueObjects\SubscriptionPeriod;
21 use Give\Subscriptions\ValueObjects\SubscriptionStatus;
22
23 /**
24 * Class LegacyPaymentGatewayAdapter
25 * @since 2.18.0
26 */
27 class LegacyPaymentGatewayAdapter
28 {
29
30 /**
31 * Get legacy form field markup to display gateway specific payment fields
32 *
33 * @since 2.18.0
34 * @since 2.19.0 Added missing $args parameter for ID prefixing and general backwards compatibility.
35 */
36 public function getLegacyFormFieldMarkup(
37 int $formId,
38 array $args,
39 PaymentGateway $registeredGateway
40 ): string {
41 return $registeredGateway->getLegacyFormFieldMarkup($formId, $args);
42 }
43
44 /**
45 * First we create a payment, then move on to the gateway processing
46 *
47 * @since 2.30.0 Add success, cancel and failed URLs to gateway data. This will be used in both v2 and v3 forms so gateways can just refer to the gateway data.
48 * @since 2.24.0 add support for payment mode
49 * @since 2.21.0 Replace give_insert_payment with donation model. Store legacy subscription data in donation meta.
50 * Attach subscription id to donation.
51 * @since 2.19.0 Replace is_recurring with is_donation_recurring to detect recurring donations.
52 * @since 2.18.0
53 *
54 * @throws Exception
55 */
56 public function handleBeforeGateway(array $legacyDonationData, PaymentGateway $registeredGateway)
57 {
58 $formData = FormData::fromRequest($legacyDonationData);
59
60 $this->validateGatewayNonce($formData->gatewayNonce);
61 $donor = $this->getOrCreateDonor(
62 $formData->donorInfo->wpUserId,
63 $formData->donorInfo->email,
64 $formData->donorInfo->firstName,
65 $formData->donorInfo->lastName
66 );
67
68 $donation = $formData->toDonation($donor->id);
69
70 if (give_recurring_is_donation_recurring($legacyDonationData)) {
71 $subscriptionData = SubscriptionData::fromRequest($legacyDonationData);
72
73 $paymentMode = !empty($legacyDonationData['payment_mode']) ? new SubscriptionMode($legacyDonationData['payment_mode']) : null;
74
75 if ( $paymentMode === null ) {
76 $paymentMode = give_is_test_mode() ? SubscriptionMode::TEST() : SubscriptionMode::LIVE();
77 }
78
79 $subscription = Subscription::create([
80 'amount' => $donation->amount,
81 'period' => new SubscriptionPeriod($subscriptionData->period),
82 'frequency' => (int)$subscriptionData->frequency,
83 'donorId' => $donor->id,
84 'installments' => (int)$subscriptionData->times,
85 'status' => SubscriptionStatus::PENDING(),
86 'mode' => $paymentMode,
87 'donationFormId' => $formData->formId,
88 ]);
89
90 $donation->type = DonationType::SUBSCRIPTION();
91 $donation->subscriptionId = $subscription->id;
92 $donation->save();
93
94 give()->subscriptions->updateLegacyParentPaymentId($subscription->id, $donation->id);
95
96 $this->setSession($donation->id);
97
98 /**
99 * Filter hook to provide gateway data before initial transaction for subscription is processed by the gateway.
100 *
101 * @since 2.21.2
102 */
103 $gatewayData = apply_filters(
104 "givewp_create_subscription_gateway_data_{$registeredGateway::id()}",
105 (new GetGatewayDataFromRequest)(),
106 $donation,
107 $subscription
108 );
109
110 $gatewayData = $this->addUrlsToGatewayData($donation, $gatewayData, $registeredGateway);
111
112 $controller = new GatewaySubscriptionController($registeredGateway);
113 $controller->create($donation, $subscription, $gatewayData);
114 } else {
115 $donation->type = DonationType::SINGLE();
116 $donation->save();
117
118 $this->setSession($donation->id);
119
120 /**
121 * Filter hook to provide gateway data before transaction is processed by the gateway.
122 *
123 * @since 2.21.2
124 */
125 $gatewayData = apply_filters(
126 "givewp_create_payment_gateway_data_{$registeredGateway::id()}",
127 (new GetGatewayDataFromRequest)(),
128 $donation
129 );
130
131 $gatewayData = $this->addUrlsToGatewayData($donation, $gatewayData, $registeredGateway);
132
133 $controller = new GatewayPaymentController($registeredGateway);
134 $controller->create($donation, $gatewayData);
135 }
136 }
137
138 /**
139 * @since 2.30.0
140 */
141 protected function getGatewayDataSuccessUrl(int $donationId): string
142 {
143 $formId = give_get_payment_form_id($donationId);
144 $isEmbedDonationForm = !Utils::isLegacyForm($formId);
145 $donationFormPageUrl = (new DonationAccessor())->get()->formEntry->currentUrl ?: get_permalink($formId);
146
147 return $isEmbedDonationForm ?
148 Utils::createSuccessPageURL($donationFormPageUrl) :
149 give_get_success_page_url();
150 }
151
152 /**
153 * @since 2.30.0
154 */
155 protected function getGatewayDataFailedUrl(int $donationId): string
156 {
157 $formId = give_get_payment_form_id($donationId);
158 $isEmbedDonationForm = !Utils::isLegacyForm($formId);
159 $donationFormPageUrl = (new DonationAccessor())->get()->formEntry->currentUrl ?: get_permalink($formId);
160
161 return $isEmbedDonationForm ?
162 Utils::createFailedPageURL($donationFormPageUrl) :
163 give_get_failed_transaction_uri();
164 }
165
166 /**
167 * @since 2.30.0
168 */
169 protected function getGatewayDataCancelUrl(int $donationId): string
170 {
171 $formId = give_get_payment_form_id($donationId);
172
173 return (new DonationAccessor())->get()->formEntry->currentUrl ?: get_permalink($formId);
174 }
175
176 /**
177 * Validate Gateway Nonce
178 *
179 * @since 2.18.0
180 */
181 private function validateGatewayNonce(string $gatewayNonce)
182 {
183 if (!wp_verify_nonce($gatewayNonce, 'give-gateway')) {
184 wp_die(
185 esc_html__(
186 'We\'re unable to recognize your session. Please refresh the screen to try again; otherwise contact your website administrator for assistance.',
187 'give'
188 ),
189 esc_html__('Error', 'give'),
190 ['response' => 403]
191 );
192 }
193 }
194
195 /**
196 * Set donation id to purchase session for use in the donation receipt.
197 *
198 * @since 2.21.0
199 *
200 * @param $donationId
201 *
202 * @return void
203 */
204 private function setSession($donationId)
205 {
206 $purchaseSession = (array)give()->session->get('give_purchase');
207
208 if ($purchaseSession && array_key_exists('purchase_key', $purchaseSession)) {
209 $purchaseSession['donation_id'] = $donationId;
210 give()->session->set('give_purchase', $purchaseSession);
211 }
212 }
213
214 /**
215 * @since 2.21.0
216 *
217 * @param int|null $userId
218 * @param string $donorEmail
219 * @param string $firstName
220 * @param string $lastName
221 *
222 * @return Donor
223 * @throws Exception
224 */
225 private function getOrCreateDonor(
226 int $userId,
227 string $donorEmail,
228 string $firstName,
229 string $lastName
230 ): Donor {
231 // first check if donor exists as a user
232 $donor = Donor::whereUserId($userId);
233
234 // If they exist as a donor & user then make sure they don't already own this email before adding to their additional emails list..
235 if ($donor && !$donor->hasEmail($donorEmail)) {
236 $donor->additionalEmails = array_merge($donor->additionalEmails ?? [], [$donorEmail]);
237 $donor->save();
238 }
239
240 // if donor is not a user than check for any donor matching this email
241 if (!$donor) {
242 $donor = Donor::whereEmail($donorEmail);
243 }
244
245 // if no donor exists then create a new one using their personal information from the form.
246 if (!$donor) {
247 $donor = Donor::create([
248 'name' => trim("$firstName $lastName"),
249 'firstName' => $firstName,
250 'lastName' => $lastName,
251 'email' => $donorEmail,
252 'userId' => $userId ?: null,
253 ]);
254 }
255
256 return $donor;
257 }
258
259 /**
260 * @since 2.29.0
261 */
262 public function addOptRefundCheckbox(int $donationId, PaymentGatewayInterface $registeredGateway)
263 {
264 $donation = Donation::find($donationId);
265 if ($donation->gatewayId === $registeredGateway::id()) {
266 ?>
267 <div id="give-gateway-opt-refund-wrap"
268 class="give-gateway-opt-refund give-admin-box-inside give-hidden">
269 <p>
270 <input type="checkbox" id="give-gateway-opt-refund" name="give_gateway_opt_refund" value="1" />
271 <label for="give-gateway-opt-refund">
272 <?php
273 esc_html_e(sprintf('Refund the donation at %s?', $registeredGateway->getName()), 'give');
274 ?>
275 </label>
276 </p>
277 </div>
278 <script>
279 if (!!document.getElementById('give-payment-status') &&
280 1 === document.querySelectorAll('div.give-admin-box > div.give-hidden[id*="opt-refund"] input[type="checkbox"]').length
281 ) {
282 document.getElementById('give-payment-status').addEventListener('change', function (event) {
283 const refundCheckbox = document.getElementById('give-gateway-opt-refund');
284
285 if (null === refundCheckbox) {
286 return;
287 }
288
289 refundCheckbox.checked = false;
290
291 if ('refunded' === event.target.value) {
292 document.getElementById('give-gateway-opt-refund-wrap').style.display = 'block';
293 } else {
294 document.getElementById('give-gateway-opt-refund-wrap').style.display = 'none';
295 }
296 });
297 }
298 </script>
299 <?php
300 }
301 }
302
303 /**
304 * @since 2.29.0
305 */
306 public function maybeRefundOnGateway(
307 int $donationId,
308 string $newStatus,
309 string $oldStatus,
310 PaymentGateway $registeredGateway
311 ) {
312 $gatewayOptRefund = ! empty($_POST['give_gateway_opt_refund']) ? give_clean($_POST['give_gateway_opt_refund']) : '';
313 $canProcessRefund = ! empty($gatewayOptRefund) ? $gatewayOptRefund : false;
314
315 // Only move forward if refund requested.
316 if ( ! $canProcessRefund) {
317 return;
318 }
319
320 $donation = Donation::find($donationId);
321 if ($donation->gatewayId === $registeredGateway::id() &&
322 'refunded' === $newStatus &&
323 'refunded' !== $oldStatus) {
324 $controller = new GatewayPaymentController($registeredGateway);
325 $controller->refund($donation);
326 }
327 }
328
329 /**
330 * @since 2.30.0
331 */
332 protected function addUrlsToGatewayData(Donation $donation, $gatewayData, PaymentGateway $registeredGateway)
333 {
334 return array_merge($gatewayData, [
335 'successUrl' => add_query_arg(
336 ['payment-confirmation' => $registeredGateway::id()],
337 $this->getGatewayDataSuccessUrl($donation->id)
338 ),
339 'cancelUrl' => $this->getGatewayDataCancelUrl($donation->id),
340 'failedUrl' => $this->getGatewayDataFailedUrl($donation->id)
341 ]);
342 }
343 }
344