{"record":{"id":"98b81afe3befb56c","repo":"nopSolutions/nopCommerce","slug":"payment-token-not-created","errorCode":null,"errorMessage":"Payment token not created","messagePattern":"Payment token not created","errorType":"exception","errorClass":"NopException","httpStatus":null,"severity":"error","filePath":"src/Plugins/Nop.Plugin.Payments.PayPalCommerce/Services/PayPalCommerceServiceManager.cs","lineNumber":2740,"sourceCode":"\n            //try to create payment token by the approved setup token\n            var payer = await PrepareBillingDetailsAsync(settings, details);\n            var paymentTokenRequest = new CreatePaymentTokenRequest\n            {\n                Customer = payer,\n                PaymentSource = new()\n                {\n                    Token = new()\n                    {\n                        Id = setupTokenId,\n                        Type = PaymentTokenType.SETUP_TOKEN.ToString().ToUpper()\n                    }\n                }\n            };\n\n            var paymentToken = await _httpClient.RequestAsync<CreatePaymentTokenRequest, CreatePaymentTokenResponse>(paymentTokenRequest, settings);\n            if (string.IsNullOrEmpty(paymentToken?.Id))\n                throw new NopException(\"Payment token not created\");\n\n            await _tokenService.InsertAsync(new()\n            {\n                ClientId = settings.ClientId,\n                CustomerId = details.Customer.Id,\n                IsPrimaryMethod = false,\n                VaultId = paymentToken.Id,\n                VaultCustomerId = paymentToken.Customer?.Id,\n                TransactionId = paymentToken.Metadata?.OrderId,\n                Type = paymentToken.PaymentSource?.Card is not null\n                    ? nameof(paymentToken.PaymentSource.Card)\n                    : (paymentToken.PaymentSource?.PayPal is not null\n                    ? nameof(paymentToken.PaymentSource.PayPal)\n                    : null)\n            });\n\n            var paymentRequest = new ProcessPaymentRequest();\n","sourceCodeStart":2722,"sourceCodeEnd":2758,"githubUrl":"https://github.com/nopSolutions/nopCommerce/blob/64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2/src/Plugins/Nop.Plugin.Payments.PayPalCommerce/Services/PayPalCommerceServiceManager.cs#L2722-L2758","documentation":"Thrown by CreateRecurringOrderAsync after calling PayPal's CreatePaymentToken endpoint when the response has no Id (string.IsNullOrEmpty(paymentToken?.Id)). The setup token was approved but PayPal did not return a usable vaulted payment token, so the local PayPalToken record cannot be created and the flow aborts.","triggerScenarios":"The setup token has expired or was revoked by the time CreatePaymentToken is called; PayPal declined to vault the payment source (e.g. card declined, source not eligible); the response payload shape changed and Id is missing.","commonSituations":"Long delay between setup-token approval and order creation so the token expired; payer removed the payment source from their PayPal vault mid-flow; PayPal account restriction prevents token creation; API version mismatch stripping the id field.","solutions":["Treat the (default, error) result as 'tokenization failed' and restart the setup-token flow to get a fresh approved token.","Ensure CreateRecurringOrderAsync is invoked promptly after setup-token approval to avoid expiry.","Confirm the PayPal REST API version / response model in use returns the token id; update the SDK/models if PayPal changed the contract."],"exampleFix":"// before\nvar (order, err) = await _serviceManager.CreateRecurringOrderAsync(settings, setupTokenId);\n\n// after\nvar (order, err) = await _serviceManager.CreateRecurringOrderAsync(settings, setupTokenId);\nif (string.IsNullOrEmpty(err) && order is null)\n{\n    // tokenization produced no token id\n    err = \"PayPal did not create a payment token; please re-approve the setup\";\n}\nif (!string.IsNullOrEmpty(err))\n{\n    ClearPendingSetupToken(orderContext);\n    NotifyError(err);\n    return;\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"var (order, error) = await mgr.CreateRecurringOrderAsync(settings, setupTokenId);\nif (!string.IsNullOrEmpty(error))\n{\n    // tokenization failed (e.g. expired/revoked setup token)\n    ClearPendingSetupToken(context);\n    NotifyError(error); // prompt user to re-approve the setup token\n    return;\n}","preventionTips":["Invoke order creation promptly after setup-token approval to avoid expiry.","Clear stale setup tokens and re-approve on failure.","Keep the PayPal API/SDK model in sync so the token id is parsed correctly."],"tags":["payments","paypal-commerce","recurring","vault","tokenization"],"backgroundTag":null,"analyzedSha":"64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2","analyzedAt":"2026-08-13T21:19:38.062Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}