craftcms / commerce-paypal-checkout

PayPal Checkout gateway for Craft Commerce.
https://plugins.craftcms.com/commerce-paypal-checkout
MIT License
5 stars 10 forks source link

"Error: Expected an order id to be passed" when using default HTML #70

Closed levinelson closed 1 year ago

levinelson commented 1 year ago

Description I'm struggling to get PayPal checkout to work as I upgrade from Craft 3 and Commerce 3 to version 4. I keep getting an alert Error: Expected an order id to be passed. It certainly used to work on Commerce 3, so I'm trying to figure out what I'm missing in the upgrade path.

When I build a form using PayPal's Integration Builder, stuff seems to generally work with my PayPal app (but I'm not sure how to then integrate that with Craft Commerce, so I'm trying to go the vanilla getPaymentFormHtml route), so I don't think its an error on the PayPal app setup side, but Craft Commerce seems to be struggling.

To Reproduce Here's my new template code (globalCart is my cart):

<form method="post">
  {{ csrfInput() }}
  {{ actionInput('commerce/payments/pay') }}
  {% namespace globalCart.gateway.handle|commercePaymentFormNamespace %}
    {{ globalCart.gateway.getPaymentFormHtml({
      currency: 'USD'
    })|raw }}
  {% endnamespace %}
</form>

Items in the cart are products using the Digital Products plugin, if that might matter.

Expected behavior The PayPal buttons render as expected, but clicking them produces an alert with the error mentioned.

Additional info

Additional context

SCR-20221123-j90

karltbone commented 1 year ago

Same thing for me on craft 3.7.44, commerce 3.4.15, php 7.4.33. the paypal plugin is using a stripe gateway with test keys. the stripe payment method works fine, but with paypal i get the same error.

secondred-rausch commented 1 year ago

Same problem for me:

Craft edition & version | Craft Pro 4.2.4 Craft Commerce | 4.1.2 PayPal Checkout for Craft Commerce | 2.1.1

in Sandbox Mode.

The error message is: Error: Expected an order id to be passed.

Without any changes from my side

nfourtythree commented 1 year ago

Hi all,

Could you check in the related cart's "Transactions" tab to see if there is a failed transaction row?

If there is a row, click on the info icon and there should be some further information in the "Gateway Message" or "Gateway Response".

Hopefully, this could point in the right direction as to what might be happening here.

Thanks!

secondred-rausch commented 1 year ago

{ "name": "UNPROCESSABLE_ENTITY", "details": [ { "field": "\/purchase_units\/@reference_id==\u0027default\u0027\/amount\/breakdown\/item_total\/value", "value": "57.1", "issue": "ITEM_TOTAL_MISMATCH", "description": "Should equal sum of (unit_amount * quantity) across all items for a given purchase_unit" } ], "message": "The requested action could not be performed, semantically incorrect, or failed business validation.", "debug_id": "2ee369dfd79c7", "links": [ { "href": "https:\/\/developer.paypal.com\/docs\/api\/orders\/v2\/#error-ITEM_TOTAL_MISMATCH", "rel": "information_link", "method": "GET" } ] }

nfourtythree commented 1 year ago

Hi @secondred-rausch

{ "name": "UNPROCESSABLE_ENTITY", "details": [ { "field": "\/purchase_units\/@reference_id==\u0027default\u0027\/amount\/breakdown\/item_total\/value", "value": "57.1", "issue": "ITEM_TOTAL_MISMATCH", "description": "Should equal sum of (unit_amount * quantity) across all items for a given purchase_unit" } ], "message": "The requested action could not be performed, semantically incorrect, or failed business validation.", "debug_id": "2ee369dfd79c7", "links": [ { "href": "https:\/\/developer.paypal.com\/docs\/api\/orders\/v2\/#error-ITEM_TOTAL_MISMATCH", "rel": "information_link", "method": "GET" } ] }

It looks like there is an issue with the totalling. What did the cart look like regarding items and their quantities and values? Do you have any custom logic for pricing products or line items?

Do you still get an error if you turn off the sending of the cart items in the gateway settings?

Thanks.

secondred-rausch commented 1 year ago

I've found the problem but don't know any solution for this on my side.

I have custom adjustments with a custom type. These add various fees to the actual line item. This adjustments are missing in the item_total in your paypal request data, cause you use: getItemSubtotal() which doesn't include my adjustments. So the total payment amount isn't the same like all the item amounts together.

Is there any solution for this? Can you integrate an event, so I can adjust the paypal request data? Or do you have the possibility to add all the adjustments, that are not a type of discount, tax or shipping to the item_total?

Thank you very much for you help!

nfourtythree commented 1 year ago

Yea this makes sense as to why you are seeing the issue.

As stated in the docs only adjuster types of tax, shipping and discount are fully supported. As with these types the system "understands" how they are applied to the line items, orders and therefore how they are passed to payment gateways.

There is a possibility to add an event to allow you to adjust the request data, although I can't give you a timeframe on when that might be.

As I asked before does the issue still persist if you turn off the "Send Cart Info" setting?

Thanks

secondred-rausch commented 1 year ago

Thank you very much for your information! I've turned off the option "Send Cart Info" and now it works. It would still be great if there were some events for that in the future.

Thank you for your help!

levinelson commented 1 year ago

The issue's persisting for me, I tried turning off Send Cart Info as well as Send Shipping Info because we're just dealing with digital products on our site. Still getting same order id error. Unfortunately no transactions showing in the cart in Admin, either.

levinelson commented 1 year ago

Would it be helpful to dump any cart or gateway info for you?

nfourtythree commented 1 year ago

Hi @levinelson

Do you get any errors in the console or any failed XHR requests that might have any information in their responses?

Thanks

levinelson commented 1 year ago

Weirdly, as I was testing again, I was able to get one PayPal payment to go through on Chrome, but now its since reverted back to the same error.

{
    "cart": {
        "number": "b1f4eb11e8ecde544a2e917c4727e7b8",
        "reference": null,
        "couponCode": null,
        "isCompleted": false,
        "dateOrdered": null,
        "datePaid": null,
        "dateAuthorized": null,
        "currency": "USD",
        "gatewayId": 3,
        "lastIp": "172.19.0.1",
        "message": null,
        "returnUrl": "/checkout/confirm",
        "cancelUrl": "/checkout",
        "orderStatusId": null,
        "orderLanguage": "en-US",
        "orderSiteId": 1,
        "origin": "web",
        "billingAddressId": null,
        "shippingAddressId": null,
        "makePrimaryShippingAddress": false,
        "makePrimaryBillingAddress": false,
        "shippingSameAsBilling": false,
        "billingSameAsShipping": false,
        "estimatedBillingAddressId": null,
        "estimatedShippingAddressId": null,
        "sourceBillingAddressId": null,
        "sourceShippingAddressId": null,
        "estimatedBillingSameAsShipping": false,
        "shippingMethodHandle": null,
        "shippingMethodName": null,
        "registerUserOnOrderComplete": false,
        "paymentSourceId": null,
        "storedTotalPrice": 55,
        "storedTotal": null,
        "storedTotalPaid": 0,
        "storedItemTotal": 55,
        "storedItemSubtotal": 55,
        "storedTotalShippingCost": 0,
        "storedTotalDiscount": 0,
        "storedTotalTax": 0,
        "storedTotalTaxIncluded": 0,
        "storedTotalQty": 1,
        "suppressEmails": false,
        "id": 69838,
        "tempId": null,
        "draftId": null,
        "revisionId": null,
        "isProvisionalDraft": false,
        "uid": "0d8ba88d-6e76-45c7-b073-6ca5d4950a02",
        "siteSettingsId": 69838,
        "fieldLayoutId": 1,
        "contentId": 18839,
        "enabled": true,
        "archived": false,
        "siteId": 1,
        "title": null,
        "slug": null,
        "uri": null,
        "dateCreated": {
            "date": "11/25/2022",
            "time": "2:32 PM"
        },
        "dateUpdated": {
            "date": "11/25/2022",
            "time": "2:36 PM"
        },
        "dateLastMerged": null,
        "dateDeleted": null,
        "trashed": false,
        "isNewForSite": false,
        "canonicalId": 69838,
        "isDraft": false,
        "isRevision": false,
        "isUnpublishedDraft": false,
        "ref": null,
        "status": "enabled",
        "structureId": null,
        "url": null,
        "adjustmentSubtotal": 0,
        "adjustmentsTotal": 0,
        "customer": {
            "photoId": null,
            "active": true,
            "pending": false,
            "locked": false,
            "suspended": false,
            "admin": false,
            "username": "admin+test-20221125E@thehappytoolbox.com",
            "email": "admin+test-20221125E@thehappytoolbox.com",
            "password": null,
            "lastLoginDate": "2022-11-25T14:35:53-08:00",
            "invalidLoginCount": null,
            "lastInvalidLoginDate": null,
            "lockoutDate": null,
            "hasDashboard": false,
            "passwordResetRequired": false,
            "lastPasswordChangeDate": null,
            "unverifiedEmail": null,
            "newPassword": null,
            "currentPassword": null,
            "verificationCodeIssuedDate": null,
            "verificationCode": null,
            "lastLoginAttemptIp": null,
            "authError": null,
            "inheritorOnDelete": null,
            "id": 69839,
            "tempId": null,
            "draftId": null,
            "revisionId": null,
            "isProvisionalDraft": false,
            "uid": "2a64f73e-5105-4287-8450-4833f5cc06df",
            "siteSettingsId": 69839,
            "fieldLayoutId": 18,
            "contentId": 18840,
            "enabled": true,
            "archived": false,
            "siteId": 1,
            "title": null,
            "slug": null,
            "uri": null,
            "dateCreated": "2022-11-25T14:33:04-08:00",
            "dateUpdated": "2022-11-25T14:33:04-08:00",
            "dateLastMerged": null,
            "dateDeleted": null,
            "trashed": false,
            "isNewForSite": false,
            "fullName": "Test Happy Jones",
            "firstName": "Test Happy",
            "lastName": "Jones",
            "canonicalId": 69839,
            "isDraft": false,
            "isRevision": false,
            "isUnpublishedDraft": false,
            "ref": "admin+test-20221125E@thehappytoolbox.com",
            "status": "active",
            "structureId": null,
            "url": null,
            "cooldownEndTime": null,
            "friendlyName": "Test Happy",
            "isCredentialed": true,
            "isCurrent": true,
            "name": "Test Happy Jones",
            "preferredLanguage": null,
            "remainingCooldownTime": null,
            "totalDownloadAttempts": 0,
            "events": {
                "fieldId": "53",
                "primaryOwnerId": null,
                "ownerId": 69839,
                "allowOwnerDrafts": null,
                "allowOwnerRevisions": null,
                "typeId": null,
                "elementType": "craft\\elements\\MatrixBlock",
                "contentTable": "{{%content}}",
                "customFields": null,
                "inReverse": false,
                "asArray": false,
                "ignorePlaceholders": false,
                "drafts": false,
                "provisionalDrafts": false,
                "draftId": null,
                "draftOf": null,
                "draftCreator": null,
                "savedDraftsOnly": false,
                "revisions": false,
                "revisionId": null,
                "revisionOf": null,
                "revisionCreator": null,
                "id": null,
                "uid": null,
                "siteSettingsId": null,
                "fixedOrder": false,
                "status": [
                    "enabled"
                ],
                "archived": false,
                "trashed": false,
                "dateCreated": null,
                "dateUpdated": null,
                "siteId": 1,
                "unique": false,
                "preferSites": null,
                "leaves": false,
                "relatedTo": null,
                "title": null,
                "slug": null,
                "uri": null,
                "search": null,
                "ref": null,
                "with": null,
                "orderBy": "",
                "withStructure": null,
                "structureId": null,
                "level": null,
                "hasDescendants": null,
                "ancestorOf": null,
                "ancestorDist": null,
                "descendantOf": null,
                "descendantDist": null,
                "siblingOf": null,
                "prevSiblingOf": null,
                "nextSiblingOf": null,
                "positionedBefore": null,
                "positionedAfter": null,
                "select": {
                    "**": "**"
                },
                "selectOption": null,
                "distinct": false,
                "from": null,
                "groupBy": null,
                "join": null,
                "having": null,
                "union": null,
                "withQueries": null,
                "params": [],
                "queryCacheDuration": null,
                "queryCacheDependency": null,
                "where": null,
                "limit": null,
                "offset": null,
                "indexBy": null,
                "emulateExecution": false,
                "hasMethods": true,
                "canSetProperties": true,
                "color": null,
                "thumbnailImage": null,
                "body": null,
                "download": null,
                "heroImage": null,
                "teaser": null,
                "legalMenu": null,
                "instagram": null,
                "twitter": null,
                "about": null,
                "models": null,
                "requirements": null,
                "fileTypes": null,
                "packs": null,
                "gallery": null,
                "youtube": null,
                "featuredPacks": null,
                "featuredVolumes": null,
                "newFeatured": null,
                "bodyMatrix": null,
                "text": null,
                "items": null,
                "heading": null,
                "image": null,
                "backgroundColor": null,
                "gradient": null,
                "video": null,
                "ogImage": null,
                "totalDownloadAttempts": null,
                "buttonLabel": null,
                "buttonLink": null,
                "displayOn": null,
                "active": null,
                "openLinkInNewTab": null,
                "trackingCode": null,
                "searchTerms": null,
                "events": null,
                "eventTitle": null,
                "properties": null,
                "timestamp": null,
                "testimonials": null,
                "personName": null,
                "logo": null,
                "quote": null,
                "personTitle": null,
                "testimonialSubhead": null,
                "testimonialHeader": null,
                "studioLicenseLabel": null,
                "licenseType": null,
                "singleLicenseLabel": null,
                "totalRevenue": null,
                "quantitySold": null,
                "packVariantLabel": null,
                "relatedPacks": null,
                "heroImageLayout": null
            }
        },
        "customerId": 69839,
        "paymentCurrency": "USD",
        "paymentAmount": 55,
        "email": "admin+test-20221125E@thehappytoolbox.com",
        "isPaid": false,
        "itemSubtotal": 55,
        "itemTotal": 55,
        "lineItems": [
            {
                "id": 20638,
                "weight": 0,
                "length": 0,
                "height": 0,
                "width": 0,
                "qty": 1,
                "note": "",
                "privateNote": "",
                "purchasableId": 20502,
                "orderId": 69838,
                "lineItemStatusId": null,
                "taxCategoryId": 1,
                "shippingCategoryId": 1,
                "dateCreated": "2022-11-25T14:32:59-08:00",
                "dateUpdated": "2022-11-25T14:36:12-08:00",
                "uid": "fb44dc6b-297d-4e14-aa53-6e9c51a4e724",
                "adjustments": [],
                "description": "Everyday People",
                "options": [],
                "optionsSignature": "d751713988987e9331980363e24189ce",
                "onSale": false,
                "price": 55,
                "saleAmount": 0,
                "salePrice": 55,
                "sku": "pack-everyday-people-1",
                "total": 55,
                "priceAsCurrency": "$55.00",
                "saleAmountAsCurrency": "$0.00",
                "salePriceAsCurrency": "$55.00",
                "subtotalAsCurrency": "$55.00",
                "totalAsCurrency": "$55.00",
                "discountAsCurrency": "$0.00",
                "shippingCostAsCurrency": "$0.00",
                "taxAsCurrency": "$0.00",
                "taxIncludedAsCurrency": "$0.00",
                "adjustmentsTotalAsCurrency": "$0.00",
                "subtotal": 55,
                "snapshot": {
                    "id": 20502,
                    "typeId": 1,
                    "taxCategoryId": 1,
                    "postDate": {
                        "date": "2021-02-23 12:19:00.000000",
                        "timezone_type": 3,
                        "timezone": "America/Los_Angeles"
                    },
                    "expiryDate": null,
                    "promotable": true,
                    "sku": "pack-everyday-people-1",
                    "price": 55,
                    "tempId": null,
                    "draftId": null,
                    "revisionId": null,
                    "isProvisionalDraft": false,
                    "uid": "0deac4c6-caef-4e12-a058-9582e46826a3",
                    "siteSettingsId": 20502,
                    "fieldLayoutId": 4,
                    "contentId": 2942,
                    "enabled": true,
                    "archived": false,
                    "siteId": 1,
                    "title": "Everyday People",
                    "slug": "everyday-people-1",
                    "uri": "pack/everyday-people-1",
                    "dateCreated": {
                        "date": "2020-09-25 12:19:25.000000",
                        "timezone_type": 3,
                        "timezone": "America/Los_Angeles"
                    },
                    "dateUpdated": {
                        "date": "2022-09-01 22:34:27.000000",
                        "timezone_type": 3,
                        "timezone": "America/Los_Angeles"
                    },
                    "dateLastMerged": null,
                    "dateDeleted": null,
                    "trashed": false,
                    "isNewForSite": false,
                    "canonicalId": 20502,
                    "isDraft": false,
                    "isRevision": false,
                    "isUnpublishedDraft": false,
                    "ref": null,
                    "status": "live",
                    "structureId": null,
                    "url": "https://happy-toolbox.ddev.site/pack/everyday-people-1",
                    "isAvailable": true,
                    "isPromotable": true,
                    "shippingCategoryId": 1,
                    "description": "Everyday People",
                    "purchasableId": 20502,
                    "cpEditUrl": "#",
                    "options": [],
                    "sales": []
                }
            }
        ],
        "orderAdjustments": [],
        "outstandingBalance": 55,
        "paidStatus": "unpaid",
        "recalculationMode": "none",
        "shortNumber": "b1f4eb1",
        "totalPaid": 0,
        "total": 55,
        "totalPrice": 55,
        "totalQty": 1,
        "totalSaleAmount": 0,
        "totalWeight": 0,
        "adjustmentSubtotalAsCurrency": "$0.00",
        "adjustmentsTotalAsCurrency": "$0.00",
        "itemSubtotalAsCurrency": "$55.00",
        "itemTotalAsCurrency": "$55.00",
        "outstandingBalanceAsCurrency": "$55.00",
        "paymentAmountAsCurrency": "$55.00",
        "totalPaidAsCurrency": "$0.00",
        "totalAsCurrency": "$55.00",
        "totalPriceAsCurrency": "$55.00",
        "totalSaleAmountAsCurrency": "$0.00",
        "totalTaxAsCurrency": "$0.00",
        "totalTaxIncludedAsCurrency": "$0.00",
        "totalShippingCostAsCurrency": "$0.00",
        "totalDiscountAsCurrency": "$0.00",
        "storedTotalAsCurrency": "$0.00",
        "storedTotalPriceAsCurrency": "$55.00",
        "storedTotalPaidAsCurrency": "$0.00",
        "storedItemTotalAsCurrency": "$55.00",
        "storedItemSubtotalAsCurrency": "$55.00",
        "storedTotalShippingCostAsCurrency": "$0.00",
        "storedTotalDiscountAsCurrency": "$0.00",
        "storedTotalTaxAsCurrency": "$0.00",
        "storedTotalTaxIncludedAsCurrency": "$0.00",
        "trackingCode": null,
        "paidStatusHtml": "<span class=\"commerceStatusLabel\"><span class=\"status red\"></span> Unpaid</span>",
        "customerLinkHtml": "<a href=\"https://happy-toolbox.ddev.site/admin/users/69839\">admin+test-20221125E@thehappytoolbox.com</a>",
        "orderStatusHtml": "",
        "totalTax": 0,
        "totalTaxIncluded": 0,
        "totalShippingCost": 0,
        "totalDiscount": 0,
        "availableShippingMethodOptions": [],
        "billingAddress": null,
        "notices": [],
        "shippingAddress": null
    },
    "paymentFormErrors": {
        "paymentMethodId": [
            "Payment Method Id cannot be blank."
        ]
    },
    "modelName": "paymentForm",
    "paymentForm": {
        "customer": null,
        "paymentMethodId": null,
        "firstName": null,
        "lastName": null,
        "number": null,
        "month": null,
        "year": null,
        "cvv": null,
        "token": null,
        "expiry": null,
        "threeDSecure": false
    },
    "errors": {
        "paymentMethodId": [
            "Payment Method Id cannot be blank."
        ]
    },
    "message": "Invalid payment or order. Please review."
}

Looks like it's telling me payment method id can't be blank? The cart has the gatewayId set, but is there something else I'm missing in the form?

nfourtythree commented 1 year ago

Hi @levinelson

Are you using the Stripe gateway at all? paymentMethodId is a required attribute on the Payment Intents PaymentForm model but PayPal doesn't have the same thing, seems like there is some confusion there as to which gateway is being used?

Thanks.

levinelson commented 1 year ago

Yes, I'm using Stripe and PayPal as the two gateway options. Default gateway is Stripe, but the user can switch to PayPal using a separate form.

Do you have advice on how/if I should change my payment form template when the user selects PayPal?

nfourtythree commented 1 year ago

Hi @levinelson

It would appear from what you sent there is a mismatch on the gateway. It is worth checking on the form that you are indeed setting the correct gatewayId when the user is selecting the PayPal gateway.

Thanks

levinelson commented 1 year ago

Thanks @nfourtythree - I simplified my "change gateway" form and all seems to be working now. I'm not sure what I missed there! Something in the Commerce 3 -> 4 transition must have made that form not work fully any more. I was confused because the PayPal buttons were indeed showing up with getPaymentForm, so that made me assume the gateway was properly set.

Thanks for the help, I'm good now!