PluginProbe
PayPlug for WooCommerce (Official) / 1.0.20
PayPlug for WooCommerce (Official) v1.0.20
3.0.0 2.18.0 1.0.17 1.0.18 1.0.19 1.0.20 1.0.21 1.0.22 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.1.0 1.10.0 1.10.1 1.2.1 1.2.10 1.2.11 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 All 101 releases
payplug / src / Gateway / PayplugResponse.php

PayplugResponse.php in PayPlug for WooCommerce (Official) 1.0.20, at src/Gateway/PayplugResponse.php

314 lines 8.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Payplug\PayplugWoocommerce\Gateway;
4
5 // Exit if accessed directly
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit;
8 }
9
10 use Payplug\PayplugWoocommerce\PayplugWoocommerceHelper;
11 use Payplug\Resource\IVerifiableAPIResource;
12 use Payplug\Resource\Payment as PaymentResource;
13 use Payplug\Resource\Refund as RefundResource;
14 use WC_Payment_Token_CC;
15
16 /**
17 * Process responses from PayPlug.
18 *
19 * @package Payplug\PayplugWoocommerce\Gateway
20 */
21 class PayplugResponse {
22
23 private $gateway;
24
25 public function __construct( PayplugGateway $gateway ) {
26 $this->gateway = $gateway;
27 }
28
29 /**
30 * Process payment.
31 *
32 * @param $resource
33 * @param $is_payment_with_token
34 *
35 * @return void
36 * @throws \WC_Data_Exception
37 */
38 public function process_payment( $resource, $is_payment_with_token = false ) {
39 $order_id = wc_clean( $resource->metadata['order_id'] );
40 $order = wc_get_order( $order_id );
41 if ( ! $order ) {
42 PayplugGateway::log( sprintf( 'Coudn\'t find order #%s (Transaction %s).', $order_id, wc_clean( $resource->id ) ), 'error' );
43
44 return;
45 }
46
47 PayplugGateway::log( sprintf( 'Order #%s : Begin processing payment IPN %s', $order_id, $resource->id ) );
48
49 // Ignore paid orders
50 if ( $order->is_paid() ) {
51 PayplugGateway::log( sprintf( 'Order #%s : Order is already complete. Ignoring IPN.', $order_id ) );
52
53 return;
54 }
55
56 // Ignore cancelled orders
57 if ( $order->has_status( 'refunded' ) ) {
58 PayplugGateway::log( sprintf( 'Order #%s : Order has been refunded. Ignoring IPN', $order_id ) );
59
60 return;
61 }
62
63 $metadata = PayplugWoocommerceHelper::extract_transaction_metadata( $resource );
64 PayplugWoocommerceHelper::save_transaction_metadata( $order, $metadata );
65
66 if ( $resource->is_paid ) {
67
68 if ( ! $is_payment_with_token ) {
69 $this->maybe_save_card( $resource );
70 }
71
72 $this->maybe_save_address_hash( $resource );
73
74 $order->add_order_note( sprintf( __( 'PayPlug IPN OK | Transaction %s', 'payplug' ), wc_clean( $resource->id ) ) );
75 $order->payment_complete( wc_clean( $resource->id ) );
76 if ( PayplugWoocommerceHelper::is_pre_30() ) {
77 $order->reduce_order_stock();
78 }
79
80 /**
81 * Fires once a payment response has been processed.
82 *
83 * @param int $order_id Order ID
84 * @param PaymentResource $resource Payment resource
85 */
86 \do_action( 'payplug_gateway_payment_response_processed', $order_id, $resource );
87
88 PayplugGateway::log( sprintf( 'Order #%s : Payment IPN %s processing completed.', $order_id, $resource->id ) );
89
90 return;
91 }
92
93 if ( ! empty( $resource->failure ) ) {
94 $order->update_status(
95 'failed',
96 sprintf( __( 'PayPlug IPN OK | Transaction %s failed : %s', 'payplug' ), $resource->id, wc_clean( $resource->failure->message ) )
97 );
98
99 /** This action is documented in src/Gateway/PayplugResponse */
100 \do_action( 'payplug_gateway_payment_response_processed', $order_id, $resource );
101
102 PayplugGateway::log( sprintf( 'Order #%s : Payment IPN %s processing completed.', $order_id, $resource->id ) );
103
104 return;
105 }
106 }
107
108 /**
109 * Process refund.
110 *
111 * @param $resource
112 *
113 * @throws \Exception
114 */
115 public function process_refund( $resource ) {
116 $transaction_id = wc_clean( $resource->payment_id );
117 $order = $this->get_order_from_transaction_id( $transaction_id );
118 if ( ! $order ) {
119 PayplugGateway::log( sprintf( 'Coudn\'t find order for transaction %s (Refund %s).', wc_clean( $resource->payment_id ), wc_clean( $resource->id ) ), 'error' );
120
121 return;
122 }
123 $order_id = PayplugWoocommerceHelper::is_pre_30() ? $order->id : $order->get_id();
124
125 PayplugGateway::log( sprintf( 'Order #%s : Begin processing refund IPN %s', $order_id, $resource->id ) );
126
127 $refund_exist = $this->refund_exist_for_order( $order_id, $resource->id );
128 if ( $refund_exist ) {
129 PayplugGateway::log( sprintf( 'Order %s : Refund has already been processed. Ignoring IPN.', $order_id ) );
130
131 return;
132 }
133
134 $refund = wc_create_refund( [
135 'amount' => ( (int) $resource->amount ) / 100,
136 'reason' => isset( $resource->metadata['reason'] ) ? $resource->metadata['reason'] : null,
137 'order_id' => (int) $order_id,
138 'refund_id' => 0,
139 'refund_payment' => false,
140 ] );
141 if ( is_wp_error( $refund ) ) {
142 PayplugGateway::log( $refund->get_error_message() );
143 }
144
145 $refund_meta_key = sprintf( '_pr_%s', wc_clean( $resource->id ) );
146 if ( PayplugWoocommerceHelper::is_pre_30() ) {
147 update_post_meta( $order_id, $refund_meta_key, $resource->id );
148 } else {
149 $order->add_meta_data( $refund_meta_key, $resource->id, true );
150 $order->save();
151 }
152
153 $note = sprintf( __( 'Refund %s : Refunded %s', 'payplug' ), wc_clean( $resource->id ), wc_price( ( (int) $resource->amount ) / 100 ) );
154 if ( ! empty( $resource->metadata['reason'] ) ) {
155 $note .= sprintf( ' (%s)', esc_html( $resource->metadata['reason'] ) );
156 }
157 $order->add_order_note( $note );
158
159 /**
160 * Fires once a refund response has been processed.
161 *
162 * @param int $order_id Order ID
163 * @param RefundResource $resource Refund resource
164 */
165 \do_action( 'payplug_gateway_refund_response_processed', $order_id, $resource );
166
167 try {
168 $payment = $this->gateway->api->payment_retrieve( $transaction_id );
169 $metadata = PayplugWoocommerceHelper::extract_transaction_metadata( $payment );
170 PayplugWoocommerceHelper::save_transaction_metadata( $order, $metadata );
171 } catch ( \Exception $e ) {}
172
173 PayplugGateway::log( sprintf( 'Order #%s : Refund IPN %s processing completed.', $order_id, $resource->id ) );
174 }
175
176 /**
177 * Get an order from its transaction id.
178 *
179 * @param int $transaction_id
180 *
181 * @return bool|\WC_Order
182 */
183 protected function get_order_from_transaction_id( $transaction_id ) {
184 global $wpdb;
185
186 $order_id = $wpdb->get_var(
187 $wpdb->prepare(
188 "
189 SELECT post_id
190 FROM $wpdb->postmeta
191 WHERE meta_key = '_transaction_id'
192 AND meta_value = %s
193 ",
194 $transaction_id
195 )
196 );
197
198 return ! is_null( $order_id ) ? wc_get_order( $order_id ) : false;
199 }
200
201 /**
202 * Check if a refund id already exist for the order.
203 *
204 * @param string $refund_id
205 *
206 * @return bool
207 */
208 protected function refund_exist_for_order( $order_id, $refund_id ) {
209 global $wpdb;
210
211 $sql = "
212 SELECT p.ID
213 FROM $wpdb->posts p
214 INNER JOIN $wpdb->postmeta pm
215 ON p.ID = pm.post_id
216 WHERE 1=1
217 AND p.post_type = %s
218 AND p.ID = %d
219 AND pm.meta_key LIKE '_pr_" . esc_sql( $refund_id ) . "'
220 AND pm.meta_value = %s
221 LIMIT 1
222 ";
223
224 $results = $wpdb->get_col(
225 $wpdb->prepare(
226 $sql,
227 'shop_order',
228 (int) $order_id,
229 $refund_id
230 )
231 );
232
233 return ! empty( $results ) ? true : false;
234 }
235
236 /**
237 * Save card from the transaction.
238 *
239 * @param IVerifiableAPIResource $resource
240 *
241 * @return bool
242 */
243 protected function maybe_save_card( $resource ) {
244
245 if ( ! isset( $resource->card ) || empty( $resource->card->id ) ) {
246 return false;
247 }
248
249 if ( ! isset( $resource->metadata['customer_id'] ) ) {
250 return false;
251 }
252
253 $customer = get_user_by( 'id', $resource->metadata['customer_id'] );
254 if ( ! $customer || 0 === (int) $customer->ID ) {
255 return false;
256 }
257
258 $merchant_id = $this->gateway->get_merchant_id();
259 if ( empty( $merchant_id ) ) {
260 return false;
261 }
262
263 PayplugGateway::log( sprintf( 'Saving card from transaction %s for customer %s', wc_clean( $resource->id ), $customer->ID ) );
264
265 $token = new WC_Payment_Token_CC();
266 $token->set_token( wc_clean( $resource->card->id ) );
267 $token->set_gateway_id( 'payplug' );
268 $token->set_last4( wc_clean( $resource->card->last4 ) );
269 $token->set_expiry_year( wc_clean( $resource->card->exp_year ) );
270 $token->set_expiry_month( zeroise( (int) wc_clean( $resource->card->exp_month ), 2 ) );
271 $token->set_card_type( \strtolower( wc_clean( $resource->card->brand ) ) );
272 $token->set_user_id( $customer->ID );
273 $token->add_meta_data( 'mode', $resource->is_live ? 'live' : 'test', true );
274 $token->add_meta_data( 'payplug_account', \wc_clean( $merchant_id ), true );
275 $token->save();
276
277 PayplugGateway::log( sprintf( 'Payment card saved', wc_clean( $resource->id ), $customer->ID ) );
278
279 return true;
280 }
281
282 /**
283 * Save shipping address.
284 *
285 * @param IVerifiableAPIResource $resource
286 *
287 * @return bool
288 */
289 protected function maybe_save_address_hash( $resource ) {
290
291 if ( ! isset( $resource->metadata['customer_id'] ) ) {
292 return false;
293 }
294
295 $customer = get_user_by( 'id', $resource->metadata['customer_id'] );
296 if ( ! $customer || 0 === (int) $customer->ID ) {
297 return false;
298 }
299
300 $shipping = [];
301 foreach ( PayplugAddressData::$address_fields as $field ) {
302 $shipping[ $field ] = $resource->shipping->{$field};
303 }
304
305 $shipping_hash = PayplugAddressData::hash_address( $shipping );
306 $hash_list = PayplugAddressData::get_customer_addresses_hash( $customer->ID );
307 $hash_list[] = $shipping_hash;
308 $hash_list = array_unique( $hash_list );
309 PayplugAddressData::update_customer_addresses_hash( $customer->ID, $hash_list );
310
311 return true;
312 }
313 }
314