@@ -29,39 +29,49 @@ public function build( ?WC_Cart $wc_cart ): array {
2929
3030 $ packages = WC ()->shipping ()->get_packages ();
3131
32- if ( empty ( $ packages ) ) {
32+ // Note: This plugin only supports a single package.
33+ // Key constraint is the PayPal API that can receive one shipping address per order.
34+ $ package = $ packages [0 ] ?? null ;
35+
36+ if ( empty ( $ package ) ) {
3337 return array ();
3438 }
3539
3640 $ chosen_methods = WC ()->session ->get ( 'chosen_shipping_methods ' );
37- $ chosen_id = ( is_array ( $ chosen_methods ) && ! empty ( $ chosen_methods ) )
38- ? $ chosen_methods [0 ]
39- : null ;
41+
42+ $ chosen_id = null ;
43+
44+ // The CartResponse schema expects only one selected shipping option.
45+ // If we have _any_ options, we pluck the first value as it's always present,
46+ // even when the session incorrectly contains multiple chosen methods.
47+ // We silently ignore cases where more than one option is chosen in the session.
48+ if ( is_array ( $ chosen_methods ) && ! empty ( $ chosen_methods ) ) {
49+ $ chosen_id = $ chosen_methods [0 ];
50+ }
4051
4152 $ currency = get_woocommerce_currency ();
4253 $ options = array ();
54+ $ all_rates = $ package ['rates ' ] ?? array ();
4355 $ first_rate_id = null ;
4456
45- foreach ( $ packages as $ package ) {
46- if ( empty ( $ package ['rates ' ] ) ) {
47- continue ;
48- }
49-
50- foreach ( $ package ['rates ' ] as $ rate ) {
51- $ rate_id = $ rate ->get_id ();
57+ foreach ( $ all_rates as $ rate ) {
58+ // Note: Rate IDs can repeat in different packages, e.g. "flat_rate:1" can apply
59+ // to all packages. We do not care about this potential repeat ID, for 2 reasons:
60+ // 1. The PayPal API only supports single-package orders.
61+ // 2. The PayPalCart only supports a single shipping method.
62+ $ rate_id = $ rate ->get_id ();
5263
53- if ( null === $ first_rate_id ) {
54- $ first_rate_id = $ rate_id ;
55- }
56-
57- $ options [] = array (
58- 'id ' => $ rate_id ,
59- 'label ' => $ rate ->get_label (),
60- 'amount ' => number_format ( (float ) $ rate ->get_cost (), 2 , '. ' , '' ),
61- 'currency ' => $ currency ,
62- 'is_selected ' => false ,
63- );
64+ if ( null === $ first_rate_id ) {
65+ $ first_rate_id = $ rate_id ;
6466 }
67+
68+ $ options [] = array (
69+ 'id ' => $ rate_id ,
70+ 'label ' => $ rate ->get_label (),
71+ 'amount ' => CartHelper::format_decimal ( $ rate ->get_cost () ),
72+ 'currency ' => $ currency ,
73+ 'is_selected ' => false ,
74+ );
6575 }
6676
6777 if ( empty ( $ options ) ) {
0 commit comments