boomerdigital / solidus_amazon_payments

Add Pay with Amazon to your Spree Commerce solution
Apache License 2.0
7 stars 8 forks source link

Address Consent Token never made available after initial login #63

Open prdanelli opened 6 years ago

prdanelli commented 6 years ago

I don't know if this is something that you decided to leave out of the gem or if the docs have been updated since, but there is no way to get the users full address (including name and address1) because Address Consent Token is never set, or made available to downstream functions after login.

As per the docs here https://pay.amazon.com/us/developer/documentation/lpwa/201953150, the following could be added to the login script:

views/spree/amazon/_login.html.erb

# ...
  <script type="text/javascript">
  var authRequest, addressConsentToken;

  OffAmazonPayments.Button("AmazonPayButton", "<%= gateway.preferred_merchant_id %>", {
    type: "PwA",
    authorization: function() {
      loginOptions = { scope: "profile postal_code payments:widget payments:shipping_address", popup: "true" };
      authRequest = amazon.Login.authorize(loginOptions, function(response) {
        addressConsentToken = response.access_token;
      });
    },
    onSignIn: function (orderReference) {
      var referenceId = orderReference.getAmazonOrderReferenceId();

     if (!referenceId) {
        this.onError(new Error('referenceId missing'));
      } else {
        window.location = "/amazon_order/address" +
          '?referenceId=' +
          orderReference.getAmazonOrderReferenceId() +
          "&access_token=" +
          addressConsentToken;
      }
    },
    onError: function(error) {
      console.log("The following error occurred: " + error.message);
    }
  });
</script>

Now the addressConsentToken is available as a param to use on the address/delivery step.

dhonig commented 6 years ago

@victorahm @acreilly Is this a feature that should be included by default or an optional feature?

prdanelli commented 6 years ago

The above is just an idea at how you could give access to the access token, but without it, the gem only returns half the address to the checkout and no names.

dhonig commented 6 years ago

Thanks @prwhitehead I just wanted to get some eyes on it that have some deeper experience with the plugin than myself.

prdanelli commented 6 years ago

Hello,

As i'm working on a project that involves integrating Amazon Pay this is how I have addressed the issue of incomplete addresses:

class Spree::AmazonController < Spree::StoreController

  # ... Removed for brevity

  before_action :set_address_consent_token, only: :address

  def delivery
    address = SpreeAmazon::Address.find(
      current_order.amazon_order_reference_id,
      gateway: gateway,
      address_consent_token: address_consent_token
    )

    current_order.state = "address"

    if address
      current_order.email = "pending@amazon.com"
      update_current_order_address!(:ship_address, address)
      update_current_order_address!(:bill_address, address)

      current_order.save!
      current_order.next!
      current_order.reload

      render layout: false
    else
      redirect_to address_amazon_order_path, notice: "Unable to load Address data from Amazon"
    end
  end

  protected

  def complete_amazon_order!
    # Pass token to the AmazonOrder accessor so we get a proper email address 
    amazon_order.address_consent_token = address_consent_token

    amazon_order.set_order_reference_details(
      current_order.total,
      seller_order_id: current_order.number,
      store_name: current_order.store.name
    )
    amazon_order.confirm
    amazon_order.fetch

    current_order.email = amazon_order.email
    update_current_order_address!(:ship_address, amazon_order.address)
  end

  def set_address_consent_token
    return unless address_consent_param.present?

    cookies.signed[:amazon_address_consent_token] = address_consent_param

    redirect_to address_amazon_order_path
  end

  def address_consent_param
    params.permit(:address_consent_token).dig(:address_consent_token)
  end

  def address_consent_token
    cookies.signed[:amazon_address_consent_token]
  end
end

The before action checks for a param and redirects back to the action once the cookie is set. This is then available other controller actions to pass around as required.

I can put this in a pull request if you would like.