Skip to content

Commit 3318ac8

Browse files
anu-rockmordethnaman03malhotradpaun1985
authored andcommitted
Store balance transaction ID in order metadata (#7945)
Co-authored-by: Cvetan Cvetanov <[email protected]> Co-authored-by: Naman Malhotra <[email protected]> Co-authored-by: Dan Paun <[email protected]>
1 parent 12cbfce commit 3318ac8

12 files changed

+125
-67
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: update
3+
4+
Store balance transaction ID in order metadata.

includes/admin/class-wc-rest-payments-orders-controller.php

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -189,19 +189,7 @@ public function capture_terminal_payment( WP_REST_Request $request ) {
189189
// Update the order: set the payment method and attach intent attributes.
190190
$order->set_payment_method( WC_Payment_Gateway_WCPay::GATEWAY_ID );
191191
$order->set_payment_method_title( __( 'WooCommerce In-Person Payments', 'woocommerce-payments' ) );
192-
$intent_id = $intent->get_id();
193-
$intent_status = $intent->get_status();
194-
$charge = $intent->get_charge();
195-
$charge_id = $charge ? $charge->get_id() : null;
196-
$this->order_service->attach_intent_info_to_order(
197-
$order,
198-
$intent_id,
199-
$intent_status,
200-
$intent->get_payment_method_id(),
201-
$intent->get_customer_id(),
202-
$charge_id,
203-
$intent->get_currency()
204-
);
192+
$this->order_service->attach_intent_info_to_order( $order, $intent );
205193
$this->order_service->update_order_status_from_intent( $order, $intent );
206194

207195
// Certain payments (eg. Interac) are captured on the client-side (mobile app).

includes/class-wc-payment-gateway-wcpay.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,7 +1689,7 @@ public function process_payment_for_order( $cart, $payment_information, $schedul
16891689
}
16901690
}
16911691

1692-
$this->order_service->attach_intent_info_to_order( $order, $intent_id, $status, $payment_method, $customer_id, $charge_id, $currency );
1692+
$this->order_service->attach_intent_info_to_order( $order, $intent );
16931693
$this->attach_exchange_info_to_order( $order, $charge_id );
16941694
if ( Intent_Status::SUCCEEDED === $status ) {
16951695
$this->duplicate_payment_prevention_service->remove_session_processing_order( $order->get_id() );
@@ -1884,7 +1884,7 @@ public function process_redirect_payment( $order, $intent_id, $save_payment_meth
18841884
}
18851885
}
18861886

1887-
$this->order_service->attach_intent_info_to_order( $order, $intent_id, $status, $payment_method_id, $customer_id, $charge_id, $currency );
1887+
$this->order_service->attach_intent_info_to_order( $order, $intent );
18881888
$this->attach_exchange_info_to_order( $order, $charge_id );
18891889
if ( Intent_Status::SUCCEEDED === $status ) {
18901890
$this->duplicate_payment_prevention_service->remove_session_processing_order( $order->get_id() );
@@ -3425,7 +3425,7 @@ public function update_order_status() {
34253425
$charge_id = ! empty( $charge ) ? $charge->get_id() : null;
34263426

34273427
$this->attach_exchange_info_to_order( $order, $charge_id );
3428-
$this->order_service->attach_intent_info_to_order( $order, $intent_id, $status, $intent->get_payment_method_id(), $intent->get_customer_id(), $charge_id, $intent->get_currency() );
3428+
$this->order_service->attach_intent_info_to_order( $order, $intent );
34293429
$this->order_service->attach_transaction_fee_to_order( $order, $charge );
34303430
} else {
34313431
// For $0 orders, fetch the Setup Intent instead.

includes/class-wc-payments-order-service.php

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ class WC_Payments_Order_Service {
113113
*/
114114
const WCPAY_MODE_META_KEY = '_wcpay_mode';
115115

116+
/**
117+
* Meta key used to store payment transaction Id.
118+
*
119+
* @const string
120+
*/
121+
const WCPAY_PAYMENT_TRANSACTION_ID_META_KEY = '_wcpay_payment_transaction_id';
122+
116123
/**
117124
* Client for making requests to the WooCommerce Payments API
118125
*
@@ -531,6 +538,23 @@ public function set_charge_id_for_order( $order, $charge_id ) {
531538
$order->save_meta_data();
532539
}
533540

541+
/**
542+
* Set the payment metadata for payment transaction id.
543+
*
544+
* @param mixed $order The order.
545+
* @param string $payment_transaction_id The value to be set.
546+
*
547+
* @throws Order_Not_Found_Exception
548+
*/
549+
public function set_payment_transaction_id_for_order( $order, $payment_transaction_id ) {
550+
if ( ! isset( $payment_transaction_id ) || null === $payment_transaction_id ) {
551+
return;
552+
}
553+
$order = $this->get_order( $order );
554+
$order->update_meta_data( self::WCPAY_PAYMENT_TRANSACTION_ID_META_KEY, $payment_transaction_id );
555+
$order->save_meta_data();
556+
}
557+
534558
/**
535559
* Get the payment metadata for charge id.
536560
*
@@ -773,17 +797,47 @@ public function get_fraud_meta_box_type_for_order( $order ) : string {
773797
/**
774798
* Given the payment intent data, adds it to the given order as metadata and parses any notes that need to be added
775799
*
800+
* @param WC_Order $order The order.
801+
* @param WC_Payments_API_Payment_Intention|WC_Payments_API_Setup_Intention $intent The payment or setup intention object.
802+
*
803+
* @throws Order_Not_Found_Exception
804+
*/
805+
public function attach_intent_info_to_order( WC_Order $order, $intent ) {
806+
// We don't want to allow metadata for a successful payment to be disrupted.
807+
if ( Intent_Status::SUCCEEDED === $this->get_intention_status_for_order( $order ) ) {
808+
return;
809+
}
810+
// first, let's prepare all the metadata needed for refunds, required for status change etc.
811+
$intent_id = $intent->get_id();
812+
$intent_status = $intent->get_status();
813+
$payment_method = $intent->get_payment_method_id();
814+
$customer_id = $intent->get_customer_id();
815+
$currency = $intent instanceof WC_Payments_API_Payment_Intention ? $intent->get_currency() : $order->get_currency();
816+
$charge = $intent instanceof WC_Payments_API_Payment_Intention ? $intent->get_charge() : null;
817+
$charge_id = $charge ? $charge->get_id() : null;
818+
$payment_transaction = $charge ? $charge->get_balance_transaction() : null;
819+
$payment_transaction_id = $payment_transaction['id'] ?? '';
820+
// next, save it in order meta.
821+
$this->attach_intent_info_to_order__legacy( $order, $intent_id, $intent_status, $payment_method, $customer_id, $charge_id, $currency, $payment_transaction_id );
822+
}
823+
824+
/**
825+
* Legacy version of the attach_intent_info_to_order method.
826+
*
827+
* TODO: This method should ultimately be merged with `attach_intent_info_to_order` and then removed.
828+
*
776829
* @param WC_Order $order The order.
777830
* @param string $intent_id The intent ID.
778831
* @param string $intent_status Intent status.
779832
* @param string $payment_method Payment method ID.
780833
* @param string $customer_id Customer ID.
781834
* @param string $charge_id Charge ID.
782835
* @param string $currency Currency code.
836+
* @param string $payment_transaction_id The transaction ID of the linked charge.
783837
*
784838
* @throws Order_Not_Found_Exception
785839
*/
786-
public function attach_intent_info_to_order( $order, $intent_id, $intent_status, $payment_method, $customer_id, $charge_id, $currency ) {
840+
public function attach_intent_info_to_order__legacy( $order, $intent_id, $intent_status, $payment_method, $customer_id, $charge_id, $currency, $payment_transaction_id = null ) {
787841
// first, let's save all the metadata that needed for refunds, required for status change etc.
788842
$order->set_transaction_id( $intent_id );
789843
$this->set_intent_id_for_order( $order, $intent_id );
@@ -792,6 +846,7 @@ public function attach_intent_info_to_order( $order, $intent_id, $intent_status,
792846
$this->set_intention_status_for_order( $order, $intent_status );
793847
$this->set_customer_id_for_order( $order, $customer_id );
794848
$this->set_wcpay_intent_currency_for_order( $order, $currency );
849+
$this->set_payment_transaction_id_for_order( $order, $payment_transaction_id );
795850
$order->save();
796851
}
797852

includes/subscriptions/class-wc-payments-invoice-service.php

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -299,15 +299,7 @@ public function get_and_attach_intent_info_to_order( $order, $intent_id ) {
299299

300300
$charge = $intent_object->get_charge();
301301

302-
$this->order_service->attach_intent_info_to_order(
303-
$order,
304-
$intent_id,
305-
$intent_object->get_status(),
306-
$intent_object->get_payment_method_id(),
307-
$intent_object->get_customer_id(),
308-
$charge ? $charge->get_id() : null,
309-
$intent_object->get_currency()
310-
);
302+
$this->order_service->attach_intent_info_to_order( $order, $intent_object );
311303
}
312304

313305
/**

src/Internal/Service/OrderService.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -186,21 +186,25 @@ public function update_order_from_successful_intent(
186186
) {
187187
$order = $this->get_order( $order_id );
188188

189-
$charge = null;
190-
$charge_id = null;
189+
$charge = null;
190+
$charge_id = null;
191+
$payment_transaction_id = null;
191192
if ( $intent instanceof WC_Payments_API_Payment_Intention ) {
192-
$charge = $intent->get_charge();
193-
$charge_id = $intent->get_charge()->get_id();
193+
$charge = $intent->get_charge();
194+
$charge_id = $intent->get_charge()->get_id();
195+
$payment_transaction = $charge ? $charge->get_balance_transaction() : null;
196+
$payment_transaction_id = $payment_transaction['id'] ?? '';
194197
}
195198

196-
$this->legacy_service->attach_intent_info_to_order(
199+
$this->legacy_service->attach_intent_info_to_order__legacy(
197200
$order,
198201
$intent->get_id(),
199202
$intent->get_status(),
200203
$context->get_payment_method()->get_id(),
201204
$context->get_customer_id(),
202205
$charge_id,
203-
$context->get_currency()
206+
$context->get_currency(),
207+
$payment_transaction_id,
204208
);
205209

206210
$this->legacy_service->attach_transaction_fee_to_order( $order, $charge );
@@ -253,7 +257,7 @@ public function update_order_from_intent_that_requires_action(
253257
) {
254258
$order = $this->get_order( $order_id );
255259

256-
$this->legacy_service->attach_intent_info_to_order(
260+
$this->legacy_service->attach_intent_info_to_order__legacy(
257261
$order,
258262
$intent->get_id(),
259263
$intent->get_status(),

tests/unit/admin/test-class-wc-rest-payments-orders-controller.php

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,7 @@ public function test_capture_terminal_payment_success() {
114114
->method( 'attach_intent_info_to_order' )
115115
->with(
116116
$this->isInstanceOf( WC_Order::class ),
117-
$this->mock_intent_id,
118-
Intent_Status::REQUIRES_CAPTURE,
119-
'pm_mock',
120-
'cus_mock',
121-
$this->mock_charge_id,
122-
'USD'
117+
$mock_intent,
123118
);
124119

125120
$request = new WP_REST_Request( 'POST' );
@@ -171,12 +166,7 @@ public function test_capture_terminal_payment_succeeded_intent() {
171166
->method( 'attach_intent_info_to_order' )
172167
->with(
173168
$this->isInstanceOf( WC_Order::class ),
174-
$this->mock_intent_id,
175-
Intent_Status::SUCCEEDED,
176-
'pm_mock',
177-
'cus_mock',
178-
$this->mock_charge_id,
179-
'USD'
169+
$mock_intent,
180170
);
181171

182172
$this->mock_gateway
@@ -236,12 +226,7 @@ public function test_capture_terminal_payment_completed_order() {
236226
->method( 'attach_intent_info_to_order' )
237227
->with(
238228
$this->isInstanceOf( WC_Order::class ),
239-
$this->mock_intent_id,
240-
Intent_Status::SUCCEEDED,
241-
'pm_mock',
242-
'cus_mock',
243-
$this->mock_charge_id,
244-
'USD'
229+
$mock_intent,
245230
);
246231

247232
$this->mock_gateway

tests/unit/helpers/class-wc-helper-intention.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,15 @@ public static function create_charge( $data = [] ) {
3838
'amount_captured' => 5000,
3939
'amount_refunded' => 0,
4040
'application_fee_amount' => 0,
41-
'balance_transaction' => 'txn_mock',
41+
'balance_transaction' => [
42+
'id' => 'txn_mock',
43+
'amount' => 5000,
44+
'available_on' => 1703808000,
45+
'created' => new DateTime( '2022-05-20 19:05:38' ),
46+
'currency' => 'usd',
47+
'exchange_rate' => null,
48+
'fee' => 82,
49+
],
4250
'billing_details' => [],
4351
'currency' => 'usd',
4452
'dispute' => [],

tests/unit/payment-methods/test-class-upe-split-payment-gateway.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ public function test_process_redirect_setup_intent_succeded() {
621621

622622
$setup_intent = WC_Helper_Intention::create_setup_intention(
623623
[
624-
'id' => 'pi_mock',
624+
'id' => $intent_id,
625625
'client_secret' => $client_secret,
626626
'status' => $intent_status,
627627
'payment_method' => $payment_method_id,

tests/unit/src/Internal/Service/OrderServiceTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ public function test_update_order_from_successful_intent( $intent ) {
332332
->willReturn( $mock_charge );
333333
}
334334

335-
// Prepare all parameters for `attach_intent_info_to_order`.
335+
// Prepare all parameters for `attach_intent_info_to_order__legacy`.
336336
$intent->expects( $this->once() )
337337
->method( 'get_id' )
338338
->willReturn( $intent_id );
@@ -355,7 +355,7 @@ public function test_update_order_from_successful_intent( $intent ) {
355355
->willReturn( 'prod' );
356356

357357
$this->mock_legacy_service->expects( $this->once() )
358-
->method( 'attach_intent_info_to_order' )
358+
->method( 'attach_intent_info_to_order__legacy' )
359359
->with(
360360
$mock_order,
361361
$intent_id,
@@ -412,7 +412,7 @@ public function test_update_order_from_intent_that_requires_action() {
412412
$mock_intent->expects( $this->once() )->method( 'get_status' )->willReturn( $intent_status );
413413

414414
$this->mock_legacy_service->expects( $this->once() )
415-
->method( 'attach_intent_info_to_order' )
415+
->method( 'attach_intent_info_to_order__legacy' )
416416
->with(
417417
$mock_order,
418418
$intent_id,

tests/unit/test-class-wc-payment-gateway-wcpay-process-payment.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ public function test_intent_status_success() {
304304
$this->mock_order_service
305305
->expects( $this->once() )
306306
->method( 'attach_intent_info_to_order' )
307-
->with( $mock_order, $intent_id, $status, 'pm_mock', $customer_id, $charge_id, 'USD' );
307+
->with( $mock_order, $intent );
308308

309309
$this->mock_order_service
310310
->expects( $this->once() )
@@ -471,7 +471,7 @@ public function test_intent_status_requires_capture() {
471471
$this->mock_order_service
472472
->expects( $this->once() )
473473
->method( 'attach_intent_info_to_order' )
474-
->with( $mock_order, $intent_id, $status, 'pm_mock', $customer_id, $charge_id, 'USD' );
474+
->with( $mock_order, $intent );
475475

476476
// Assert: The Order_Service is called correctly.
477477
$this->mock_order_service
@@ -919,7 +919,7 @@ public function test_intent_status_requires_action() {
919919
$this->mock_order_service
920920
->expects( $this->once() )
921921
->method( 'attach_intent_info_to_order' )
922-
->with( $mock_order, $intent_id, $status, 'pm_mock', $customer_id, $charge_id, 'USD' );
922+
->with( $mock_order, $intent );
923923

924924
$this->mock_order_service
925925
->expects( $this->once() )
@@ -1035,7 +1035,7 @@ public function test_setup_intent_status_requires_action() {
10351035
$this->mock_order_service
10361036
->expects( $this->once() )
10371037
->method( 'attach_intent_info_to_order' )
1038-
->with( $mock_order, $intent_id, $status, 'pm_mock', $customer_id, '', 'USD' );
1038+
->with( $mock_order, $intent );
10391039

10401040
// Assert: Order status was not updated.
10411041
$mock_order

tests/unit/test-class-wc-payments-order-service.php

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,18 +1211,40 @@ public function test_get_fraud_meta_box_type() {
12111211
$this->assertEquals( $fraud_meta_box_type_from_service, $fraud_meta_box_type );
12121212
}
12131213

1214+
public function test_set_payment_transaction_id_for_order() {
1215+
$transaction_id = 'txn_mock';
1216+
$this->order_service->set_payment_transaction_id_for_order( $this->order, $transaction_id );
1217+
$this->assertSame( $this->order->get_meta( '_wcpay_payment_transaction_id', true ), $transaction_id );
1218+
}
1219+
12141220
public function test_attach_intent_info_to_order() {
1215-
$intent_id = 'pi_mock';
1216-
$intent_status = 'succeeded';
1217-
$payment_method = 'woocommerce_payments';
1218-
$customer_id = 'cus_12345';
1219-
$charge_id = 'ch_mock';
1220-
$currency = 'USD';
1221-
$this->order_service->attach_intent_info_to_order( $this->order, $intent_id, $intent_status, $payment_method, $customer_id, $charge_id, $currency );
1221+
$intent_id = 'pi_mock';
1222+
$intent = WC_Helper_Intention::create_intention( [ 'id' => $intent_id ] );
1223+
$this->order_service->attach_intent_info_to_order( $this->order, $intent );
12221224

12231225
$this->assertEquals( $intent_id, $this->order->get_meta( '_intent_id', true ) );
12241226
}
12251227

1228+
public function test_attach_intent_info_to_order_after_successful_payment() {
1229+
$intent = WC_Helper_Intention::create_intention(
1230+
[
1231+
'id' => 'pi_mock',
1232+
'status' => Intent_Status::SUCCEEDED,
1233+
]
1234+
);
1235+
$this->order_service->attach_intent_info_to_order( $this->order, $intent );
1236+
1237+
$another_intent = WC_Helper_Intention::create_intention(
1238+
[
1239+
'id' => 'pi_mock_2',
1240+
'status' => Intent_Status::CANCELED,
1241+
]
1242+
);
1243+
$this->order_service->attach_intent_info_to_order( $this->order, $another_intent );
1244+
1245+
$this->assertEquals( Intent_Status::SUCCEEDED, $this->order->get_meta( '_intention_status', true ) );
1246+
}
1247+
12261248
/**
12271249
* Several methods use the private method get_order to get the order being worked on. If an order is not found
12281250
* then an exception is thrown. This test attempt to confirm that exception gets thrown.

0 commit comments

Comments
 (0)