New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should API support billing address capture (for tax computation)? #27

Open
ianbjacobs opened this Issue Mar 9, 2016 · 58 comments

Comments

@ianbjacobs
Collaborator

ianbjacobs commented Mar 9, 2016

During the Feb FTF meeting [1], Vincent Kuntz pointed out that in Europe, billing address is required to compute VAT. The use case is that you purchase something in one country (where VAT is applied) but it is being shipped to another.

Thus, for some tax computations, do we need billing address (or some portion of it, like "country")?

[1] https://www.w3.org/2016/02/24-wpwg-minutes

@mattsaxon mattsaxon added this to the Priority: High milestone Mar 21, 2016

@djackso3

This comment has been minimized.

Show comment
Hide comment
@djackso3

djackso3 Apr 8, 2016

The method by which many payment systems work (especially in card) is to verify against billing address so billing address is required for some payment types and providers. In addition, some items will require the KYC address (government functions like BMV transactions). Delivery address is not always interesting to the payments process itself, but could be used if there is an AML issue with respect to shipping location of product that requires filtering by the payments provider. Lastly, a growing number of consumers provide KYC address -- because it is legally mandated -- and billing address for convenience -- yet have a fluctuating shipping address which generally in not germane to the payments process -- however, could be for filtering requirements as mentioned above. There are excellent examples of payment systems which cease working because of confusion of KYC / billing address having a mismatch against shipping address at the merchant. Personally over the last 6 months I have been working with Bank of America on this exact issue. The bank made an IT change which confused KYC and billing address. Once that happened, Delta Airlines refused to accept payment for a ticket because of the mismatch issue. My "delivery" address at the merchant (Delta) was equal to the billing address. So when I changed to the KYC address for approval of the payment, Delta refused again because they had a merchant mismatch of their delivery address of record with the physical (KYC) address I attempted to use. For this reason -- until finally adjusted by BofA (after first flat refusing the issue) -- I could not use my card at Delta because I could not figure out what address they believed they were verifying against. It took months for me to get them to believe it an issue and they claimed that KYC = billing address (which is of course false). I explain in more detail because the issue is with respect to lack of consistent definition. There is another further example of a bank confusing "mailing" address and "billing" address. In short, the bank verified against "billing" address but their database did not equate mailing=billing so the bank rejected the verification because no "billing" address was on file and there was a mismatch against KYC.

I believe that there is reason that all three -- with consistent definition -- may need to be part of the protocol because of the fluidity for people with various reasons to maintain a shipment location for goods and "letter" or USPS location for "billing". And both of these are not the KYC address because the merchant never has a reason to collect the actual KYC address. Help?

djackso3 commented Apr 8, 2016

The method by which many payment systems work (especially in card) is to verify against billing address so billing address is required for some payment types and providers. In addition, some items will require the KYC address (government functions like BMV transactions). Delivery address is not always interesting to the payments process itself, but could be used if there is an AML issue with respect to shipping location of product that requires filtering by the payments provider. Lastly, a growing number of consumers provide KYC address -- because it is legally mandated -- and billing address for convenience -- yet have a fluctuating shipping address which generally in not germane to the payments process -- however, could be for filtering requirements as mentioned above. There are excellent examples of payment systems which cease working because of confusion of KYC / billing address having a mismatch against shipping address at the merchant. Personally over the last 6 months I have been working with Bank of America on this exact issue. The bank made an IT change which confused KYC and billing address. Once that happened, Delta Airlines refused to accept payment for a ticket because of the mismatch issue. My "delivery" address at the merchant (Delta) was equal to the billing address. So when I changed to the KYC address for approval of the payment, Delta refused again because they had a merchant mismatch of their delivery address of record with the physical (KYC) address I attempted to use. For this reason -- until finally adjusted by BofA (after first flat refusing the issue) -- I could not use my card at Delta because I could not figure out what address they believed they were verifying against. It took months for me to get them to believe it an issue and they claimed that KYC = billing address (which is of course false). I explain in more detail because the issue is with respect to lack of consistent definition. There is another further example of a bank confusing "mailing" address and "billing" address. In short, the bank verified against "billing" address but their database did not equate mailing=billing so the bank rejected the verification because no "billing" address was on file and there was a mismatch against KYC.

I believe that there is reason that all three -- with consistent definition -- may need to be part of the protocol because of the fluidity for people with various reasons to maintain a shipment location for goods and "letter" or USPS location for "billing". And both of these are not the KYC address because the merchant never has a reason to collect the actual KYC address. Help?

@djackso3

This comment has been minimized.

Show comment
Hide comment
@djackso3

djackso3 Apr 8, 2016

Before others say it -- there is a case that "shipping" address never enters the payments process and is only in the eCommerce flow. I can see this, however, I do see the continued confusion related to "billing", "mailing", "physical", "home", and other labels lacking consistency ... just an idea for consideration ...

djackso3 commented Apr 8, 2016

Before others say it -- there is a case that "shipping" address never enters the payments process and is only in the eCommerce flow. I can see this, however, I do see the continued confusion related to "billing", "mailing", "physical", "home", and other labels lacking consistency ... just an idea for consideration ...

@burdges

This comment has been minimized.

Show comment
Hide comment
@burdges

burdges Apr 8, 2016

VAT rules in Europe get tricky, but :

  • If there is a shipping address, then shipping address, not billing address, that determines the VAT the merchant pays, so the merchant already knows this.
  • It's illegal to change the advertised price based on VAT recomputation, so the VAT rate cannot impact the payment directly.
  • If the merchant needs information from the PSP for their VAT payments, then they would probably prefer it as an end of year tax statement.
  • There are no requirements on Payment App, PSPs, etc. to provide any information. It true many do so, but sometimes as a tax statement, and sometimes as a paid tax related service.
  • Address capture increases the merchant's liabilities under the E.U. Data Protection Directive too, so the PSP to anonymizing data, or doing tax form for you, may actually have value over collecting the data yourself.

I think the fraud reasons @djackso3 highlights sound more critical than VAT since VAT rate cannot impact the sale. It's true some merchants could save money by processing this information themselves, assuming their PSP chooses to make it available.

A Payment App, PSP, etc. should never be forced to make this information available however. And they should not provide it unless the merchant actually requests it.

burdges commented Apr 8, 2016

VAT rules in Europe get tricky, but :

  • If there is a shipping address, then shipping address, not billing address, that determines the VAT the merchant pays, so the merchant already knows this.
  • It's illegal to change the advertised price based on VAT recomputation, so the VAT rate cannot impact the payment directly.
  • If the merchant needs information from the PSP for their VAT payments, then they would probably prefer it as an end of year tax statement.
  • There are no requirements on Payment App, PSPs, etc. to provide any information. It true many do so, but sometimes as a tax statement, and sometimes as a paid tax related service.
  • Address capture increases the merchant's liabilities under the E.U. Data Protection Directive too, so the PSP to anonymizing data, or doing tax form for you, may actually have value over collecting the data yourself.

I think the fraud reasons @djackso3 highlights sound more critical than VAT since VAT rate cannot impact the sale. It's true some merchants could save money by processing this information themselves, assuming their PSP chooses to make it available.

A Payment App, PSP, etc. should never be forced to make this information available however. And they should not provide it unless the merchant actually requests it.

@halindrome

This comment has been minimized.

Show comment
Hide comment
@halindrome

halindrome Apr 8, 2016

Contributor

VAT rules are quite different than the rules in the US. These vary by state, and within states by governmental district (county, city, etc.) Speaking as a merchant, I need to know a number of things about the purchaser to decide what sales tax to apply to the sale. But in general the rule is to use the shipping / use address to decide what sales tax to use, and then the billing address if a shipping / use address is not available. And yes, this does effect ultimate amount that is paid by the purchaser. Sales tax is passed on to the customer in the US in most cases.

Contributor

halindrome commented Apr 8, 2016

VAT rules are quite different than the rules in the US. These vary by state, and within states by governmental district (county, city, etc.) Speaking as a merchant, I need to know a number of things about the purchaser to decide what sales tax to apply to the sale. But in general the rule is to use the shipping / use address to decide what sales tax to use, and then the billing address if a shipping / use address is not available. And yes, this does effect ultimate amount that is paid by the purchaser. Sales tax is passed on to the customer in the US in most cases.

@adrianhopebailie

This comment has been minimized.

Show comment
Hide comment
@adrianhopebailie

adrianhopebailie Apr 10, 2016

Collaborator

We must distinguish between data that is required for processing the payment and data that is being requested to streamline the checkout flow.

@djackso3 said:

The method by which many payment systems work (especially in card) is to verify against billing address so billing address is required for some payment types and providers. In addition, some items will require the KYC address (government functions like BMV transactions).

Which implies that this data is required for payment processing and should be gathered by the payment app.

However, data that is required to calculate a final amount (i.e. it impacts the tax rate) should be supported as something that can be requested from the user agent so that the website has an opportunity to recalculate the final amount prior to the request being passed to the payment app.

Collaborator

adrianhopebailie commented Apr 10, 2016

We must distinguish between data that is required for processing the payment and data that is being requested to streamline the checkout flow.

@djackso3 said:

The method by which many payment systems work (especially in card) is to verify against billing address so billing address is required for some payment types and providers. In addition, some items will require the KYC address (government functions like BMV transactions).

Which implies that this data is required for payment processing and should be gathered by the payment app.

However, data that is required to calculate a final amount (i.e. it impacts the tax rate) should be supported as something that can be requested from the user agent so that the website has an opportunity to recalculate the final amount prior to the request being passed to the payment app.

@adrianhopebailie adrianhopebailie modified the milestones: Priority: High, Discuss on Call - 28 April, Discuss on Call - 5 May Apr 22, 2016

@adrianhopebailie adrianhopebailie modified the milestones: 12 May, 5 May May 12, 2016

@dlongley

This comment has been minimized.

Show comment
Hide comment
@dlongley

dlongley May 12, 2016

The more things we keep trying to add the more I tend to think that a better design would be to provide new elements/components that merchants can put in their website to simply customize their checkout page. For example:

<shipping-address on-change="callme(event)"></shipping-address>

<billing-address on-change="callme(event)"></billing-address>

This component could be provided by the browser (or a polyfill), it could refuse to give access to the site (to JavaScript) any of choices shown to the user until one is selected, fire an "on address change" event when the user changes their address -- and let the merchant site customize their checkout experience around it. This would be a low-level component-based approach to providing a better checkout experience whilst also leveraging the browser's ability to provide this kind of information.

The idea that we're going to be able to specify every checkout flow (or "at least" the common ones) and do so in a sensible way I think is perhaps not as achievable as we'd like to think. When the checkout flow doesn't work for the merchant, they have to abandon the whole API and start from scratch. Wouldn't it be better to build out some components (that could also be polyfilled) that a merchant can use to assemble their own checkout experience?

With this approach they can configure it however they like -- update address/shipping options as they please and so forth, and still leverage the information that the user agent can provide to them. Then, once the final price has been calculated, they can call the payment request API with all of the requisite information they've collected to cause the user to select a payment app to complete the payment.

dlongley commented May 12, 2016

The more things we keep trying to add the more I tend to think that a better design would be to provide new elements/components that merchants can put in their website to simply customize their checkout page. For example:

<shipping-address on-change="callme(event)"></shipping-address>

<billing-address on-change="callme(event)"></billing-address>

This component could be provided by the browser (or a polyfill), it could refuse to give access to the site (to JavaScript) any of choices shown to the user until one is selected, fire an "on address change" event when the user changes their address -- and let the merchant site customize their checkout experience around it. This would be a low-level component-based approach to providing a better checkout experience whilst also leveraging the browser's ability to provide this kind of information.

The idea that we're going to be able to specify every checkout flow (or "at least" the common ones) and do so in a sensible way I think is perhaps not as achievable as we'd like to think. When the checkout flow doesn't work for the merchant, they have to abandon the whole API and start from scratch. Wouldn't it be better to build out some components (that could also be polyfilled) that a merchant can use to assemble their own checkout experience?

With this approach they can configure it however they like -- update address/shipping options as they please and so forth, and still leverage the information that the user agent can provide to them. Then, once the final price has been calculated, they can call the payment request API with all of the requisite information they've collected to cause the user to select a payment app to complete the payment.

@ianbjacobs

This comment has been minimized.

Show comment
Hide comment
@ianbjacobs

ianbjacobs May 12, 2016

Collaborator

-1 to including generic UI bits in the API. I think that will make it harder to gain adoption on the browser side.

Ian

Collaborator

ianbjacobs commented May 12, 2016

-1 to including generic UI bits in the API. I think that will make it harder to gain adoption on the browser side.

Ian

@dlongley

This comment has been minimized.

Show comment
Hide comment
@dlongley

dlongley May 12, 2016

@ianbjacobs,

I'm not a fan of the "all or nothing" design approach. What if we got to REC and didn't specify how to collect some piece of information that is required but the available choices are dependent upon some other piece of information we do collect via the API? Now that part of the API can't be sensibly used and has to be reimplemented on the merchant site.

Starting with a low-level design and providing higher-level options would avoid these scenarios and potentially increase adoption on the merchant side. It would also help browsers understand how merchants are putting the components together to build good checkout experiences -- which would be valuable data for them to use to improve their own higher-level options.

But I do agree that if browsers are disinterested in providing low-level components/APIs to merchants to allow them to construct better customized checkout experiences for more complex cases, this is a non-starter.

dlongley commented May 12, 2016

@ianbjacobs,

I'm not a fan of the "all or nothing" design approach. What if we got to REC and didn't specify how to collect some piece of information that is required but the available choices are dependent upon some other piece of information we do collect via the API? Now that part of the API can't be sensibly used and has to be reimplemented on the merchant site.

Starting with a low-level design and providing higher-level options would avoid these scenarios and potentially increase adoption on the merchant side. It would also help browsers understand how merchants are putting the components together to build good checkout experiences -- which would be valuable data for them to use to improve their own higher-level options.

But I do agree that if browsers are disinterested in providing low-level components/APIs to merchants to allow them to construct better customized checkout experiences for more complex cases, this is a non-starter.

@adrianhopebailie adrianhopebailie modified the milestones: 12 May, 19 May May 18, 2016

@adrianhopebailie adrianhopebailie removed this from the 19 May milestone May 24, 2016

@adrianhopebailie

This comment has been minimized.

Show comment
Hide comment
@adrianhopebailie

adrianhopebailie May 24, 2016

Collaborator

Postponed for reconsideration based on feedback per group resolution on 19 May call

Collaborator

adrianhopebailie commented May 24, 2016

Postponed for reconsideration based on feedback per group resolution on 19 May call

@tetsuharu

This comment has been minimized.

Show comment
Hide comment
@tetsuharu

tetsuharu Apr 25, 2017

At Weebly over here, implementing PaymentRequestAPI and AndroidPay, we definitely want access to billingAddress in the PaymentRequest object before committing the transaction, as well as a paymentoptionchange event for calculating tax.

tetsuharu commented Apr 25, 2017

At Weebly over here, implementing PaymentRequestAPI and AndroidPay, we definitely want access to billingAddress in the PaymentRequest object before committing the transaction, as well as a paymentoptionchange event for calculating tax.

@marcoscaceres

This comment has been minimized.

Show comment
Hide comment
@marcoscaceres

marcoscaceres Apr 26, 2017

Member

@tetsuharu, will discuss on tomorrow's Editor's call. Will report back soon.

Member

marcoscaceres commented Apr 26, 2017

@tetsuharu, will discuss on tomorrow's Editor's call. Will report back soon.

@burdges

This comment has been minimized.

Show comment
Hide comment
@burdges

burdges Apr 26, 2017

Access to customer data should require actual interaction with the customer.

burdges commented Apr 26, 2017

Access to customer data should require actual interaction with the customer.

@marcoscaceres

This comment has been minimized.

Show comment
Hide comment
@marcoscaceres

marcoscaceres Apr 26, 2017

Member

Access to customer data should require actual interaction with the customer.

I'm not sure I fully grasp what you mean? can you please clarify.

Member

marcoscaceres commented Apr 26, 2017

Access to customer data should require actual interaction with the customer.

I'm not sure I fully grasp what you mean? can you please clarify.

@burdges

This comment has been minimized.

Show comment
Hide comment
@burdges

burdges Apr 26, 2017

You cannot reveal any information about the customer without clearly obtaining their consent to reveal it, which requires displaying that information on the screen and the user taking an approval action.

I'm likely behind the times but previously the first interaction like that was show(), so the website could not access billing address, payment address, etc. before show().

burdges commented Apr 26, 2017

You cannot reveal any information about the customer without clearly obtaining their consent to reveal it, which requires displaying that information on the screen and the user taking an approval action.

I'm likely behind the times but previously the first interaction like that was show(), so the website could not access billing address, payment address, etc. before show().

@marcoscaceres marcoscaceres referenced this issue Jul 6, 2018

Open

Support requesting billing address #749

1 of 8 tasks complete
@marcoscaceres

This comment has been minimized.

Show comment
Hide comment
@marcoscaceres

marcoscaceres Jul 6, 2018

Member

Pull request sent: #749

Interested folks - would appreciate your review and comments.

Member

marcoscaceres commented Jul 6, 2018

Pull request sent: #749

Interested folks - would appreciate your review and comments.

@marcoscaceres

This comment has been minimized.

Show comment
Hide comment
@marcoscaceres

marcoscaceres Jul 6, 2018

Member

(note: I'm sending this in two parts... first part just has the event... sending a second PR for the error reporting part)

Member

marcoscaceres commented Jul 6, 2018

(note: I'm sending this in two parts... first part just has the event... sending a second PR for the error reporting part)

@marcoscaceres marcoscaceres referenced this issue Jul 6, 2018

Closed

Add error reporting billing address #750

1 of 8 tasks complete
@marcoscaceres

This comment has been minimized.

Show comment
Hide comment
@marcoscaceres

marcoscaceres Jul 6, 2018

Member

Ok, part 2 is up #750 🎁🎉

Member

marcoscaceres commented Jul 6, 2018

Ok, part 2 is up #750 🎁🎉

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Jul 9, 2018

Collaborator

So I'm reviewing some patches, but then I went over to look at the basic card spec, and see it currently requires a "billingAddress". The only mention I found of basic card in this thread via Ctrl+F was #27 (comment).

How is this reconciled? Is "basic card billing address" distinct from "PaymentRequest payer address"? Will UIs have three separate address fields, if the web developer passes requestPayerAddress and also uses basic-card? Or is there a plan to somehow sunset billingAddress from basic card?

Collaborator

domenic commented Jul 9, 2018

So I'm reviewing some patches, but then I went over to look at the basic card spec, and see it currently requires a "billingAddress". The only mention I found of basic card in this thread via Ctrl+F was #27 (comment).

How is this reconciled? Is "basic card billing address" distinct from "PaymentRequest payer address"? Will UIs have three separate address fields, if the web developer passes requestPayerAddress and also uses basic-card? Or is there a plan to somehow sunset billingAddress from basic card?

@marcoscaceres

This comment has been minimized.

Show comment
Hide comment
@marcoscaceres

marcoscaceres Jul 10, 2018

Member

The only mention I found of basic card in this thread via Ctrl+F was #27 (comment).

Apologies, we discussed it on the call and neglected to link to the minutes here (though the minutes also do a poor job reflecting the discussion - as my recollection is having discussed sunsetting Basic Card's billingAddress):
https://www.w3.org/2018/06/28-wpwg-minutes#item02

How is this reconciled? Is "basic card billing address" distinct from "PaymentRequest payer address"?

They should be the same.

Will UIs have three separate address fields, if the web developer passes requestPayerAddress and also uses basic-card?

I would expect not.

Or is there a plan to somehow sunset billingAddress from basic card?

Yes, that's the idea - but might be hard. Unfortunately, billingAddress is shipped for a while now, so might be hard to deprecate... I've be expecting the same reference (or copy) for both addresses.

New payment handlers, at least, won't have this problem (🤞).

Member

marcoscaceres commented Jul 10, 2018

The only mention I found of basic card in this thread via Ctrl+F was #27 (comment).

Apologies, we discussed it on the call and neglected to link to the minutes here (though the minutes also do a poor job reflecting the discussion - as my recollection is having discussed sunsetting Basic Card's billingAddress):
https://www.w3.org/2018/06/28-wpwg-minutes#item02

How is this reconciled? Is "basic card billing address" distinct from "PaymentRequest payer address"?

They should be the same.

Will UIs have three separate address fields, if the web developer passes requestPayerAddress and also uses basic-card?

I would expect not.

Or is there a plan to somehow sunset billingAddress from basic card?

Yes, that's the idea - but might be hard. Unfortunately, billingAddress is shipped for a while now, so might be hard to deprecate... I've be expecting the same reference (or copy) for both addresses.

New payment handlers, at least, won't have this problem (🤞).

@rsolomakhin

This comment has been minimized.

Show comment
Hide comment
@rsolomakhin

rsolomakhin Jul 26, 2018

Collaborator

Do we have any clear ideas on how to reconcile this with 3rd party payment apps?

Collaborator

rsolomakhin commented Jul 26, 2018

Do we have any clear ideas on how to reconcile this with 3rd party payment apps?

@ianbjacobs

This comment has been minimized.

Show comment
Hide comment
@ianbjacobs

ianbjacobs Jul 30, 2018

Collaborator

Hi @rsolomakhin, good question.

Would this work:

  • The payment handler returns billing address information in the Payment Handler API response.
  • Upon receipt the browser fires "onbillingaddresschange" which enables the merchant to update
    the total. If the payment handler does not return a billing address (e.g., because the payment
    method does not require it, or the transaction does not require it, or the user has not provided
    one), no event fires.
  • If the billing address has an impact on the total, then the merchant can update it in the sheet,
    prompting the user to confirm (with a message indicating that the total has changed based
    on the billing address). If the billing address does not have an impact on the total, then the
    merchant can simply close the sheet at that point.

Does that make sense?

Ian

Collaborator

ianbjacobs commented Jul 30, 2018

Hi @rsolomakhin, good question.

Would this work:

  • The payment handler returns billing address information in the Payment Handler API response.
  • Upon receipt the browser fires "onbillingaddresschange" which enables the merchant to update
    the total. If the payment handler does not return a billing address (e.g., because the payment
    method does not require it, or the transaction does not require it, or the user has not provided
    one), no event fires.
  • If the billing address has an impact on the total, then the merchant can update it in the sheet,
    prompting the user to confirm (with a message indicating that the total has changed based
    on the billing address). If the billing address does not have an impact on the total, then the
    merchant can simply close the sheet at that point.

Does that make sense?

Ian

@rsolomakhin

This comment has been minimized.

Show comment
Hide comment
@rsolomakhin

rsolomakhin Jul 30, 2018

Collaborator

Hi @ianbjacobs,

Thank you for providing some ideas. I'm not 100% clear on the timing of these events as you envision them, so let's chat about this some more the next time we're on a call. Is that OK?

Cheers,
Rouslan

Collaborator

rsolomakhin commented Jul 30, 2018

Hi @ianbjacobs,

Thank you for providing some ideas. I'm not 100% clear on the timing of these events as you envision them, so let's chat about this some more the next time we're on a call. Is that OK?

Cheers,
Rouslan

@ianbjacobs

This comment has been minimized.

Show comment
Hide comment
@ianbjacobs

ianbjacobs Jul 30, 2018

Collaborator

Yes, let's chat more this week.

Maybe no event is required. Could the merchant use retry() if the billing address affects the total?

Ian

Collaborator

ianbjacobs commented Jul 30, 2018

Yes, let's chat more this week.

Maybe no event is required. Could the merchant use retry() if the billing address affects the total?

Ian

@ianbjacobs

This comment has been minimized.

Show comment
Hide comment
@ianbjacobs

ianbjacobs Aug 3, 2018

Collaborator

Hi all,

Here is some additional thinking about billing address and third party payment handlers.

  • Due to the nature of some payment methods (e.g., real-time financing, push payments), payment should not happen until after the "definitive" billing address is known to the payment handler.
  • Today we do not have a way for the payment handler to tell the merchant "here is the definitive billing address". Indeed, by design we don't have a way for the payment handler to interact with the merchant directly for any data updates.
  • Instead, updates happen in the sheet through user interaction. Events fire and the merchant can update the total, etc.
  • One approach is to say that the "definitive billing address" is the one provided by the user, before the payment handler is selected. The user might choose a billing address from a list stored by the browser. This would cause an event to fire and the merchant could update the total. Then the user could select the payment handler and the payment handler could receive the user-asserted billing address.
  • Once in the payment handler, if the billing address is correct, everybody is happy and payment can take place.
  • However, if the billing address differs from one known within the payment handler, we have an issue. One option is to allow the payment handler to ask the user to confirm a new billing address. If the user agrees, then fire an event to tell the merchant, which can update the total which is given to the payment handler.

One way to do this is through some sort of payment handler retry() mechanism, where the payment handler tells the browser (upon action by the user):

  • Close the payment handler window and return to the sheet
  • Ask the user to confirm the billing address (populated with the data from the payment handler)
  • If the user does, that triggers the onbillingaddresschange event and the merchant can update the total.
  • Then the user reselects the payment handler and starts again, this time with the proper billing address and total.

In other words: let's have all the data updates happen in the sheet so that the merchant can learn about them through events.

This would allow the payment handler to proceed to payment if it wants, or ask for a correction by the user (in the sheet) before proceeding to payment.

I realize this will be a non-pipeline user experience, and thus could potentially be confusing. I welcome suggestions for handling this in other ways, but I note that retry() from the merchant side is not likely to work in general because payment may have already happened (with a potentially incorrect total) by the time the merchant gets to do a retry().

There may also be some ways to simplify the user experience of getting the definitive billing address from the user:

  • If the merchant does not request billing address, there is no need to surface UX for it.

  • If the merchant does request billing address the browser does not have to surface UX for it initially.
    a) If the user chooses a card stored in the browser (which has associated billing address), there is no need to surface UX for choosing billing address; the event can fire with the card's billing address.
    b) If the user chooses a third party payment handler, the browser could (finally) surface UX to prompt the user to confirm or enter the billing address before launching the payment handler. There might be some options to make this smooth, such as choosing from among:

    • "Same as shipping address"
    • Choosing the most recently used billing address with that payment handler.
    • The ability to choose from among billing addressed stored with instruments in the browser.
    • Other manually added billing addresses.

    Once the billing address has been selected, the browser then launches the payment handler.

My "hope" is that the billing address is correct most of the time, and thus the "payment handler retry()" UX is not necessary often.

By the way, it has been pointed out to me that billing address information for tax purposes may also become a more important consideration in the US [1].

Ian
[1] https://www.nytimes.com/2018/06/21/us/politics/supreme-court-sales-taxes-internet-merchants.html

Collaborator

ianbjacobs commented Aug 3, 2018

Hi all,

Here is some additional thinking about billing address and third party payment handlers.

  • Due to the nature of some payment methods (e.g., real-time financing, push payments), payment should not happen until after the "definitive" billing address is known to the payment handler.
  • Today we do not have a way for the payment handler to tell the merchant "here is the definitive billing address". Indeed, by design we don't have a way for the payment handler to interact with the merchant directly for any data updates.
  • Instead, updates happen in the sheet through user interaction. Events fire and the merchant can update the total, etc.
  • One approach is to say that the "definitive billing address" is the one provided by the user, before the payment handler is selected. The user might choose a billing address from a list stored by the browser. This would cause an event to fire and the merchant could update the total. Then the user could select the payment handler and the payment handler could receive the user-asserted billing address.
  • Once in the payment handler, if the billing address is correct, everybody is happy and payment can take place.
  • However, if the billing address differs from one known within the payment handler, we have an issue. One option is to allow the payment handler to ask the user to confirm a new billing address. If the user agrees, then fire an event to tell the merchant, which can update the total which is given to the payment handler.

One way to do this is through some sort of payment handler retry() mechanism, where the payment handler tells the browser (upon action by the user):

  • Close the payment handler window and return to the sheet
  • Ask the user to confirm the billing address (populated with the data from the payment handler)
  • If the user does, that triggers the onbillingaddresschange event and the merchant can update the total.
  • Then the user reselects the payment handler and starts again, this time with the proper billing address and total.

In other words: let's have all the data updates happen in the sheet so that the merchant can learn about them through events.

This would allow the payment handler to proceed to payment if it wants, or ask for a correction by the user (in the sheet) before proceeding to payment.

I realize this will be a non-pipeline user experience, and thus could potentially be confusing. I welcome suggestions for handling this in other ways, but I note that retry() from the merchant side is not likely to work in general because payment may have already happened (with a potentially incorrect total) by the time the merchant gets to do a retry().

There may also be some ways to simplify the user experience of getting the definitive billing address from the user:

  • If the merchant does not request billing address, there is no need to surface UX for it.

  • If the merchant does request billing address the browser does not have to surface UX for it initially.
    a) If the user chooses a card stored in the browser (which has associated billing address), there is no need to surface UX for choosing billing address; the event can fire with the card's billing address.
    b) If the user chooses a third party payment handler, the browser could (finally) surface UX to prompt the user to confirm or enter the billing address before launching the payment handler. There might be some options to make this smooth, such as choosing from among:

    • "Same as shipping address"
    • Choosing the most recently used billing address with that payment handler.
    • The ability to choose from among billing addressed stored with instruments in the browser.
    • Other manually added billing addresses.

    Once the billing address has been selected, the browser then launches the payment handler.

My "hope" is that the billing address is correct most of the time, and thus the "payment handler retry()" UX is not necessary often.

By the way, it has been pointed out to me that billing address information for tax purposes may also become a more important consideration in the US [1].

Ian
[1] https://www.nytimes.com/2018/06/21/us/politics/supreme-court-sales-taxes-internet-merchants.html

@marcoscaceres

This comment has been minimized.

Show comment
Hide comment
@marcoscaceres

marcoscaceres Aug 8, 2018

Member

I'd like to exhaust @michelle's current proposal, which is #749. Honestly, the above sounds extremely complicated, and would like the various UX teams to explore how it might work best (the requirement is clear: "merchant needs the billing address to calculate, user want to protect their privacy until they hit pay" - let's leave it at that and lets explore how far we get).

Member

marcoscaceres commented Aug 8, 2018

I'd like to exhaust @michelle's current proposal, which is #749. Honestly, the above sounds extremely complicated, and would like the various UX teams to explore how it might work best (the requirement is clear: "merchant needs the billing address to calculate, user want to protect their privacy until they hit pay" - let's leave it at that and lets explore how far we get).

@ianbjacobs

This comment has been minimized.

Show comment
Hide comment
@ianbjacobs

ianbjacobs Aug 8, 2018

Collaborator

Hi @marcoscaceres,

I think one answer to "how far we can get" is "browser-stored cards." It is not clear to me from #749 how third party payment handlers would work.

Ian

Collaborator

ianbjacobs commented Aug 8, 2018

Hi @marcoscaceres,

I think one answer to "how far we can get" is "browser-stored cards." It is not clear to me from #749 how third party payment handlers would work.

Ian

@marcoscaceres

This comment has been minimized.

Show comment
Hide comment
@marcoscaceres

marcoscaceres Aug 8, 2018

Member

Ok, but that’s a UX problem no? Or do we expect payment handlers to provide the billing address?

Put differently, we know that we want:

  1. Merchants to be able to request the billing address.
  2. When the user selects a billing address, the address is sent to the merchant so they can calculate tax.
  3. A means to update the total if needed (solved by ev.updateWith(), and retry()).

If the UA exclusively holds the billing address(es), then the above holds. If the payment handler holds the billing address, then we need to have a more detailed discussion... but it feels like that discussion is outside the scope of v1, personally.

Member

marcoscaceres commented Aug 8, 2018

Ok, but that’s a UX problem no? Or do we expect payment handlers to provide the billing address?

Put differently, we know that we want:

  1. Merchants to be able to request the billing address.
  2. When the user selects a billing address, the address is sent to the merchant so they can calculate tax.
  3. A means to update the total if needed (solved by ev.updateWith(), and retry()).

If the UA exclusively holds the billing address(es), then the above holds. If the payment handler holds the billing address, then we need to have a more detailed discussion... but it feels like that discussion is outside the scope of v1, personally.

@ianbjacobs

This comment has been minimized.

Show comment
Hide comment
@ianbjacobs

ianbjacobs Aug 8, 2018

Collaborator

@marcoscaceres wrote:
"Or do we expect payment handlers to provide the billing address?"

Yes. My current understanding is that a payment instrument will have a billing address associated with it. For those payment instruments controlled by payment handler, they will therefore "own" the billing address.

@marcoscaceres wrote:
"If the payment handler holds the billing address, then we need to have a more detailed discussion...

Yes, that is why I included the detail above. I agree it's not simple at first glance.

@marcoscaceres wrote:
"but it feels like that discussion is outside the scope of v1, personally."

Perhaps. That should be an explicit decision of the group.

Ian

Collaborator

ianbjacobs commented Aug 8, 2018

@marcoscaceres wrote:
"Or do we expect payment handlers to provide the billing address?"

Yes. My current understanding is that a payment instrument will have a billing address associated with it. For those payment instruments controlled by payment handler, they will therefore "own" the billing address.

@marcoscaceres wrote:
"If the payment handler holds the billing address, then we need to have a more detailed discussion...

Yes, that is why I included the detail above. I agree it's not simple at first glance.

@marcoscaceres wrote:
"but it feels like that discussion is outside the scope of v1, personally."

Perhaps. That should be an explicit decision of the group.

Ian

@marcoscaceres

This comment has been minimized.

Show comment
Hide comment
@marcoscaceres

marcoscaceres Aug 9, 2018

Member

Yes. My current understanding is that a payment instrument will have a billing address associated with it. For those payment instruments controlled by payment handler, they will therefore "own" the billing address.

Ok, so, if billing addresses are bound to payment instruments, then paymentmethodchange might again be the right fit (as shown by Apple Pay).

Then a redacted address can be sent back with the event's methodDetails, allowing .updateWith() to be called. Similarly, then .retry() can be used when checking the PaymentResponse.

We can then work out what each dictionary looks like, but essentially, they can each have a PaymentAddress attached as needed, or sometimes null.

For each payment method, we can define a base dictionary that everyone could use:

dictionary PaymentMethod {
   PaymentAddress? billingAddress;
}

// for paymentmethodchange, for example:
dictionary BasicCardChangeDetails  : PaymentMethod {
   // inherits billingAddress;
}

dictionary BasicCardResponse  : PaymentMethod {
  // inherits billingAddress;
  // card number, etc.
}
Member

marcoscaceres commented Aug 9, 2018

Yes. My current understanding is that a payment instrument will have a billing address associated with it. For those payment instruments controlled by payment handler, they will therefore "own" the billing address.

Ok, so, if billing addresses are bound to payment instruments, then paymentmethodchange might again be the right fit (as shown by Apple Pay).

Then a redacted address can be sent back with the event's methodDetails, allowing .updateWith() to be called. Similarly, then .retry() can be used when checking the PaymentResponse.

We can then work out what each dictionary looks like, but essentially, they can each have a PaymentAddress attached as needed, or sometimes null.

For each payment method, we can define a base dictionary that everyone could use:

dictionary PaymentMethod {
   PaymentAddress? billingAddress;
}

// for paymentmethodchange, for example:
dictionary BasicCardChangeDetails  : PaymentMethod {
   // inherits billingAddress;
}

dictionary BasicCardResponse  : PaymentMethod {
  // inherits billingAddress;
  // card number, etc.
}
@ianbjacobs

This comment has been minimized.

Show comment
Hide comment
@ianbjacobs

ianbjacobs Aug 9, 2018

Collaborator

Hi @marcoscaceres,

I may not have understood your proposal fully. However, if the proposal anticipates that the merchant only receives a billing address after the payment handler has been launched, then I think the proposal will be inadequate for use cases where:

  • Payment happens within the payment handler (e.g., form sof push payment)
  • Agreements between the user and their PSP happen within the payment handler and likely depend on the total being accurate (e.g., real-time credit offers).

Ian

Collaborator

ianbjacobs commented Aug 9, 2018

Hi @marcoscaceres,

I may not have understood your proposal fully. However, if the proposal anticipates that the merchant only receives a billing address after the payment handler has been launched, then I think the proposal will be inadequate for use cases where:

  • Payment happens within the payment handler (e.g., form sof push payment)
  • Agreements between the user and their PSP happen within the payment handler and likely depend on the total being accurate (e.g., real-time credit offers).

Ian

@marcoscaceres

This comment has been minimized.

Show comment
Hide comment
@marcoscaceres

marcoscaceres Aug 10, 2018

Member

I’m going to defer this for a while until I can educate myself on those kinds of payments.

If there are some good resources on how push payments work, happy to have a read.

If we want to solve for basic-card and other card based payments, happy to continue on this.

Member

marcoscaceres commented Aug 10, 2018

I’m going to defer this for a while until I can educate myself on those kinds of payments.

If there are some good resources on how push payments work, happy to have a read.

If we want to solve for basic-card and other card based payments, happy to continue on this.

@ianbjacobs

This comment has been minimized.

Show comment
Hide comment
@ianbjacobs

ianbjacobs Aug 10, 2018

Collaborator

@rsolomakhin and I discussed this further today and I anticipate he will write up something sensible when time permits. At a high level, we discussed this type of flow which is a better experience than the one I had in mind.

  • The user has not yet selected a billing address.
  • The user selects a payment handler.
  • Within the payment handler, the user selects a payment instrument with associated billing address.
  • The payment handler informs the browser that the user has selected a billing address. The payment handler waits for a response (read: promise to resolve) that may update the total. The payment handler will not complete the transaction until hearing back from the merchant.
  • The browser fires the onpaymentmethodchange event to let the merchant know the billing address has changed.
  • The merchant responds with a (possibly null) update of the total.
  • The browser gives the (possibly updated) total back to the payment handler.
  • The payment handler displays the total and allows the user to proceed.

@marcoscaceres, regarding push v pull payments, here's a piece by Adrian Hope-Bailie:

A Push Payments Manifesto
https://adrian.hopebailie.com/a-push-payments-manifesto-2d8ff105f48a

Examples: wire payments, ACH payments, SEPA credit transfers, Boleto Bancário, bitcoin, various real-time payments systems, etc. I invite others who know more about payments to list some useful resources.

Ian

Collaborator

ianbjacobs commented Aug 10, 2018

@rsolomakhin and I discussed this further today and I anticipate he will write up something sensible when time permits. At a high level, we discussed this type of flow which is a better experience than the one I had in mind.

  • The user has not yet selected a billing address.
  • The user selects a payment handler.
  • Within the payment handler, the user selects a payment instrument with associated billing address.
  • The payment handler informs the browser that the user has selected a billing address. The payment handler waits for a response (read: promise to resolve) that may update the total. The payment handler will not complete the transaction until hearing back from the merchant.
  • The browser fires the onpaymentmethodchange event to let the merchant know the billing address has changed.
  • The merchant responds with a (possibly null) update of the total.
  • The browser gives the (possibly updated) total back to the payment handler.
  • The payment handler displays the total and allows the user to proceed.

@marcoscaceres, regarding push v pull payments, here's a piece by Adrian Hope-Bailie:

A Push Payments Manifesto
https://adrian.hopebailie.com/a-push-payments-manifesto-2d8ff105f48a

Examples: wire payments, ACH payments, SEPA credit transfers, Boleto Bancário, bitcoin, various real-time payments systems, etc. I invite others who know more about payments to list some useful resources.

Ian

@adrianhopebailie

This comment has been minimized.

Show comment
Hide comment
@adrianhopebailie

adrianhopebailie Aug 13, 2018

Collaborator

@marcoscaceres the key difference with push is that by the time the website gets the PaymentResponse the payment is complete.

You could even think of a payment method like PayPal as "push" in some contexts, in that:
the merchant calls PR API -> the user selects PayPal -> the user authorises the payment with PayPal -> the merchant gets back a PaymentResponse

Compared with BasicCard, for example, the merchant has nothing more to do but mark the sale asd complete. The payment is already done.

Collaborator

adrianhopebailie commented Aug 13, 2018

@marcoscaceres the key difference with push is that by the time the website gets the PaymentResponse the payment is complete.

You could even think of a payment method like PayPal as "push" in some contexts, in that:
the merchant calls PR API -> the user selects PayPal -> the user authorises the payment with PayPal -> the merchant gets back a PaymentResponse

Compared with BasicCard, for example, the merchant has nothing more to do but mark the sale asd complete. The payment is already done.

@marcoscaceres marcoscaceres removed their assignment Aug 14, 2018

@marcoscaceres

This comment has been minimized.

Show comment
Hide comment
@marcoscaceres

marcoscaceres Aug 14, 2018

Member

@ianbjacobs:

@rsolomakhin and I discussed this further today and I anticipate he will write up something sensible when time permits. At a high level, we discussed this type of flow which is a better experience than the one I had in mind.

I don't understand how this is different from what I had proposed in the pull request? Could you please comment on the pull request? It seems like a waste of time for @rsolomakhin to have to redo what I already worked on? I don't see anything in your points that my pull request didn't already do.

The only difference from the points above is that there event was sent to the PaymentRequest (.onpayerdetailchange), instead of the onpaymentmethodchange, but that's just a detail.

Wrote @adrianhopebailie:

@marcoscaceres the key difference with push is that by the time the website gets the PaymentResponse the payment is complete.

Sure. I get that part.

Compared with BasicCard, for example, the merchant has nothing more to do but mark the sale as complete. The payment is already done.

I'm still not following :(

Member

marcoscaceres commented Aug 14, 2018

@ianbjacobs:

@rsolomakhin and I discussed this further today and I anticipate he will write up something sensible when time permits. At a high level, we discussed this type of flow which is a better experience than the one I had in mind.

I don't understand how this is different from what I had proposed in the pull request? Could you please comment on the pull request? It seems like a waste of time for @rsolomakhin to have to redo what I already worked on? I don't see anything in your points that my pull request didn't already do.

The only difference from the points above is that there event was sent to the PaymentRequest (.onpayerdetailchange), instead of the onpaymentmethodchange, but that's just a detail.

Wrote @adrianhopebailie:

@marcoscaceres the key difference with push is that by the time the website gets the PaymentResponse the payment is complete.

Sure. I get that part.

Compared with BasicCard, for example, the merchant has nothing more to do but mark the sale as complete. The payment is already done.

I'm still not following :(

@marcoscaceres

This comment has been minimized.

Show comment
Hide comment
@marcoscaceres

marcoscaceres Aug 14, 2018

Member

@adrianhopebailie just to be clear, when I say "I'm still not following :(", I mean I'm unsure what I should change in the pull request that I made to meet the use case. I need direct feedback on the pull request itself.

Member

marcoscaceres commented Aug 14, 2018

@adrianhopebailie just to be clear, when I say "I'm still not following :(", I mean I'm unsure what I should change in the pull request that I made to meet the use case. I need direct feedback on the pull request itself.

@adrianhopebailie

This comment has been minimized.

Show comment
Hide comment
@adrianhopebailie

adrianhopebailie Aug 14, 2018

Collaborator

@marcoscaceres I don't think you need to change the PRs but perhaps there is a need to add something that shows how a PaymentHandler may cause the Payer address changed algorithm to be invoked (when a user provides a billing address through interaction with the PaymentHandler).

Q: Are you suggesting the spec text that describes how a Payment Handler might invoke the Payer address changed algorithm doesn't belong in the PaymentRequest but rather in the PaymentHandler spec?

Push Payments and retry()*

The underlying issue related to push payments is not with Billing Address but with retry(). It is too late to call retry() if the payment handler has already completed the payment. So, while a Billing Address issue may be one reason to call retry() it's not the root of the issue.

I don't think retry() is a good idea and I think what @ianbjacobs and @rsolomakhin are attempting to do is find a flow that avoids needing it.

Collaborator

adrianhopebailie commented Aug 14, 2018

@marcoscaceres I don't think you need to change the PRs but perhaps there is a need to add something that shows how a PaymentHandler may cause the Payer address changed algorithm to be invoked (when a user provides a billing address through interaction with the PaymentHandler).

Q: Are you suggesting the spec text that describes how a Payment Handler might invoke the Payer address changed algorithm doesn't belong in the PaymentRequest but rather in the PaymentHandler spec?

Push Payments and retry()*

The underlying issue related to push payments is not with Billing Address but with retry(). It is too late to call retry() if the payment handler has already completed the payment. So, while a Billing Address issue may be one reason to call retry() it's not the root of the issue.

I don't think retry() is a good idea and I think what @ianbjacobs and @rsolomakhin are attempting to do is find a flow that avoids needing it.

@adrianhopebailie

This comment has been minimized.

Show comment
Hide comment
@adrianhopebailie

adrianhopebailie Aug 14, 2018

Collaborator

@marcoscaceres @ianbjacobs @rsolomakhin I am throwing this idea in the ring: #759

because I think it would make solving this case a LOT easier.

Collaborator

adrianhopebailie commented Aug 14, 2018

@marcoscaceres @ianbjacobs @rsolomakhin I am throwing this idea in the ring: #759

because I think it would make solving this case a LOT easier.

@ianbjacobs

This comment has been minimized.

Show comment
Hide comment
@ianbjacobs

ianbjacobs Aug 14, 2018

Collaborator

@adrianhopebailie and @marcoscaceres,

To help discussion around this issue I have started to catalog proposals (that I've heard) for handling push payments:
https://github.com/w3c/payment-request/wiki/PushPayments

Ian

Collaborator

ianbjacobs commented Aug 14, 2018

@adrianhopebailie and @marcoscaceres,

To help discussion around this issue I have started to catalog proposals (that I've heard) for handling push payments:
https://github.com/w3c/payment-request/wiki/PushPayments

Ian

@rsolomakhin

This comment has been minimized.

Show comment
Hide comment
@rsolomakhin

rsolomakhin Aug 14, 2018

Collaborator

@marcoscaceres's pull request #749 for payer address looks good to me.

My discussion with @ianbjacobs concerned primarily figuring out how to make it work with payment handlers, which we have figured out, I believe, in a way compatible with #749.

Payment Handler discussion can get a bit complicated, so it's better to keep it on the Payment Handler page, IMHO. But let me break that rule myself already: @adrianhopebailie, for what it's worth, I believe a retry() would not make sense for push payments. The purpose of retry() is to correct data errors that prevented the merchant from initiating the transaction. Since the merchant is not in charge of initiating the transaction in push payment scenario, the retry() does not need to be used in that particular case.

Collaborator

rsolomakhin commented Aug 14, 2018

@marcoscaceres's pull request #749 for payer address looks good to me.

My discussion with @ianbjacobs concerned primarily figuring out how to make it work with payment handlers, which we have figured out, I believe, in a way compatible with #749.

Payment Handler discussion can get a bit complicated, so it's better to keep it on the Payment Handler page, IMHO. But let me break that rule myself already: @adrianhopebailie, for what it's worth, I believe a retry() would not make sense for push payments. The purpose of retry() is to correct data errors that prevented the merchant from initiating the transaction. Since the merchant is not in charge of initiating the transaction in push payment scenario, the retry() does not need to be used in that particular case.

@marcoscaceres

This comment has been minimized.

Show comment
Hide comment
@marcoscaceres

marcoscaceres Aug 28, 2018

Member

So, I'm still worried about the whole billing address being tied to an instrument thing. For instance, I just bought a present for someone, and I obviously don't want to send the recipient the invoice. The website gave me these options:

screenshot 2018-08-28 15 53 45

It seems like this is not that uncommon. What am I missing?

Member

marcoscaceres commented Aug 28, 2018

So, I'm still worried about the whole billing address being tied to an instrument thing. For instance, I just bought a present for someone, and I obviously don't want to send the recipient the invoice. The website gave me these options:

screenshot 2018-08-28 15 53 45

It seems like this is not that uncommon. What am I missing?

@marcoscaceres

This comment has been minimized.

Show comment
Hide comment
@marcoscaceres

marcoscaceres Aug 28, 2018

Member

(I guess the billing address is not used for invoicing but only for verification of the card)

Member

marcoscaceres commented Aug 28, 2018

(I guess the billing address is not used for invoicing but only for verification of the card)

@snez

This comment has been minimized.

Show comment
Hide comment
@snez

snez Sep 10, 2018

Just adding a bit to the discussion - a billing address is really important when trying to perform any type of fraud prevention. When making a payment request, banks will compare the billing address to the real cardholder's address before declining a payment for fraud reasons.

Furthermore, many eCommerce platforms have been designed with a Billing Address as a minimum requirement for placing an order. Not providing a method to collect it makes the PaymentRequestAPI unsuitable for use on most major eCommerce platforms running on millions of websites.

Also for virtual/digital products, there is no shipping/delivery address, so you'd be inclined to skip the delivery address collection, however how is the merchant supposed to know the address of the customer if that is needed for any reason? This is usually why eCommerce platforms collect a billing address as a minimum, even for virtual products.

snez commented Sep 10, 2018

Just adding a bit to the discussion - a billing address is really important when trying to perform any type of fraud prevention. When making a payment request, banks will compare the billing address to the real cardholder's address before declining a payment for fraud reasons.

Furthermore, many eCommerce platforms have been designed with a Billing Address as a minimum requirement for placing an order. Not providing a method to collect it makes the PaymentRequestAPI unsuitable for use on most major eCommerce platforms running on millions of websites.

Also for virtual/digital products, there is no shipping/delivery address, so you'd be inclined to skip the delivery address collection, however how is the merchant supposed to know the address of the customer if that is needed for any reason? This is usually why eCommerce platforms collect a billing address as a minimum, even for virtual products.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment