woocommerce / woocommerce-gateway-stripe

The official Stripe Payment Gateway for WooCommerce
https://wordpress.org/plugins/woocommerce-gateway-stripe/
235 stars 206 forks source link

Apple Pay postcode backfill blocks address checks #2645

Open peterspicer-unfold opened 1 year ago

peterspicer-unfold commented 1 year ago

Describe the bug When the shipping address is supplied by Apple Pay, it is only initially a partial postcode, backfilled in this plugin with * symbols. This backfilling makes it impossible to do certain address checks correctly for shipping types.

In our case, shipping from London to central Brighton (BN1 postcode) has one pricing structure, while shipping further west such as Lancing (BN15) has a different price.

But since the postcode is padded with * characters, the same as the wildcard character, we cannot differentiate between BN1* and BN15* with Apple Pay.

To Reproduce Steps to reproduce the behavior:

  1. Have separate shipping restrictions for BN1 * vs BN15* - note that we cannot just insert a rule for BN1* because that will match BN1 and BN15 when it shouldn't.
  2. Add a shipping address in Apple Pay for a BN1 postcode.
  3. Attempt to buy - the shipping address is rejected since BN1**** doesn't match either BN1 * or any other BN1x (e.g. BN15*) rules

Expected behavior A clear and concise description of what you expected to happen.

Screenshots If applicable, add screenshots to help explain your problem.

Environment (please complete the following information):

Additional context

The change to fix this is very simple in class-wc-stripe-payment-request.php, in method get_normalized_postal_code, the following code is present:

        if ( 'GB' === $country ) {
            // Replaces a redacted string with something like LN10***.
            return str_pad( preg_replace( '/\s+/', '', $postcode ), 7, '*' );
        }

This just needs to use any character other than * to be able to differentiate between a digit and a wildcard - I've tested this with # and it seems to work as I'd expect.

majikandy commented 6 days ago

@peterspicer-unfold Having faced the exact same issue as you describe in the UK with postcodes and shipping zones, I dug deeper into how Apple Pay truncates the postcodes in the UK (I haven't looked at Canada) and I implemented a fix that allows the original shipping zone regexes to work like N1 * matching N1 postcodes and avoiding N10, N11, N12, N13, N14, N15, N16, N17, N18, and N19 without the user needing to know the # knowledge that you embedded into your fix.

The way Apple truncates turns out to be a really good implementation and actually keeps the space if it is there. It also truncates at the right point irrespective of the space, so it must do a real validation on the postcode and not just a naive truncation. Which is great for us!!

The one thing that definitely can't be fixed is where full postcodes are used in the regex, and this can never work with Apple Pay unfortunately so something like this would need to be solved a different way in the setup. We used to use this after a customer would email asking if we'd deliver and then we check it out on google maps and see how viable, and if ok we'd add an explicit postcode. Those users we need to tell them just not to use apple pay to complete the purchase.

Btw I did try your code and it did work, but it was bugging me that I needed to have N1# and N1 in my regexes so that the Apple Pay and non Apple Pay payment methods were correctly matched.

I have put this manually onto my e-commerce site and it is working as expected. If you want to try it with your own Apple Pay on my site before adding to yours just let me know.

peterspicer-unfold commented 6 days ago

I agree, it's a better fix than mine - but the client in question has long since moved on as this was over a year ago.

Though I will note that part of the reason I did fix it the way I fixed it was because I wasn't sure how long it would take for this fix to get included so in the meantime I did a bit of fiddling with the woocommerce_cart_shipping_packages hook (which would survive other updates to this plugin in the interim) to change the postcode in the first place, and then reverse engineered this fix from that and do so in a way that would mean it would just work when it got patched without me having to explicitly monitor it.