Highlights
Revamped Payment Provider interface
Warning
Breaking changes
The payment provider interface, originally designed for Medusa V1, has now been redesigned for V2–a long overdue update. These changes deliver a more unified and intuitive API.
We apologise in advance for the inconvenience it might cause for your payment provider implementations.
The following are breaking changes:
Payment Provider interface
export interface IPaymentProvider {
...
- initiatePayment(
- data: CreatePaymentProviderSession
- ): Promise<PaymentProviderError | PaymentProviderSessionResponse>
+ initiatePayment(data: InitiatePaymentInput): Promise<InitiatePaymentOutput>
- updatePayment(
- context: UpdatePaymentProviderSession
- ): Promise<PaymentProviderError | PaymentProviderSessionResponse>
+ updatePayment(data: UpdatePaymentInput): Promise<UpdatePaymentOutput>
- deletePayment(
- paymentSessionData: Record<string, unknown>
- ): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
+ deletePayment(data: DeletePaymentInput): Promise<DeletePaymentOutput>
- authorizePayment(
- paymentSessionData: Record<string, unknown>,
- context: Record<string, unknown>
- ): Promise<PaymentProviderError | PaymentProviderAuthorizeResponse>
+ authorizePayment(data: AuthorizePaymentInput): Promise<AuthorizePaymentOutput>
- capturePayment(
- paymentSessionData: Record<string, unknown>
- ): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
+ capturePayment(data: CapturePaymentInput): Promise<CapturePaymentOutput>
- refundPayment(
- paymentSessionData: Record<string, unknown>,
- refundAmount: BigNumberInput
- ): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
+ refundPayment(data: RefundPaymentInput): Promise<RefundPaymentOutput>
- retrievePayment(
- paymentSessionData: Record<string, unknown>
- ): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
+ retrievePayment(data: RetrievePaymentInput): Promise<RetrievePaymentOutput>
- cancelPayment(
- paymentSessionData: Record<string, unknown>
- ): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
+ cancelPayment(data: CancelPaymentInput): Promise<CancelPaymentOutput>
+
+ createAccountHolder?(
+ data: CreateAccountHolderInput
+ ): Promise<CreateAccountHolderOutput>
+
+ deleteAccountHolder?(
+ data: DeleteAccountHolderInput
+ ): Promise<DeleteAccountHolderOutput>
- listPaymentMethods?(
- context: PaymentProviderContext
- ): Promise<PaymentMethodResponse[]>
+ listPaymentMethods?(
+ data: ListPaymentMethodsInput
+ ): Promise<ListPaymentMethodsOutput>
- savePaymentMethod?(
- input: SavePaymentMethod
- ): Promise<PaymentProviderError | SavePaymentMethodResponse>
+ savePaymentMethod?(
+ data: SavePaymentMethodInput
+ ): Promise<SavePaymentMethodOutput>
- getPaymentStatus(
- paymentSessionData: Record<string, unknown>
- ): Promise<PaymentSessionStatus>
+ getPaymentStatus(data: GetPaymentStatusInput): Promise<GetPaymentStatusOutput>
}
The input and return types of the updated interface can be found in this file.
Additionally, we've updated the interface to require payment providers to throw errors instead of returning them to the upstream payment module service.
Create Payment Sessions endpoint
In addition to the interface changes, we've also removed the context
field from the endpoint creating payment sessions:
`POST /store/payment-collections/:id/payment-sessions
This change addresses a security risk. The context
accepted by the payment module now only accept known fields, limiting the surface area of what can be passed through it.
Account Holders
Fortunately, the revamp did not only introduce breaking changes. This release also introduces support for Account Holders in payment providers. In Stripe, for example, we will create a customer for every signed up user on your platform so you can track payments more easily within Stripe. These methods are optional for payment providers.
You can find all the changes in this pull request.
Overriding Shipping Option for Fulfillments
Note
Schemas changes
This release improves fulfillment capabilities, allowing merchants to override the shipping option originally selected during order creation. For example, a different shipping option can now be specified directly in the dashboard when creating a fulfillment.
Key changes:
- Product <> Shipping Profile link
A link between Products and Shipping Profiles has been introduced, similar to the relationship in Medusa V1. Products now require a Shipping Profile upon creation. The create and update forms in the dashboard have been updated accordingly.
- Override Shipping Option on Fulfillments
The fulfillment creation endpoint now accept an optional shipping_option_id
. If passed, it will override the shipping option used when placing the order.
POST /admin/orders/:id/fulfillments
{ ..., shipping_option_id: "so_1234"}
This functionality is also available in the dashboard, allowing merchants to specify the override when creating a fulfillment.
- Data migration script
Since products now require a shipping profile, this release includes a data migration script. The script will assign all products to the default shipping profile, if it exists. The default shipping profile is determined by looking for a shipping profile with default
(case insensitive) in its name.
By default, data migration scripts run as part of the medusa db:migrate
command.
Alternatively, you can run the data migration separately from the regular database migrations. To do this, first run the migration command with an argument skipping scripts:
medusa db:migrate --skip-scripts
Then, run the command again without the argument:
medusa db:migrate
Type-hinting for custom module services
This release improves type-hinting for custom module services. The input types of autogenerated create and update methods will provide an approximate type inferred from the related data model. Please note, in this first iteration, all properties will be marked as optional in the type, even though they might be required at the DB-level. We intend to further improve this to bring the type even closer to what the database expects.
Clearing workflow_execution
s exceeding their retention time
Note
Schemas changes
This release introduces a recurring job within the workflow engine to clear stale workflow executions from the database. The job runs every hour and deletes workflow executions that have exceeded their configured retention time.
Retention time is set in the workflow execution options. However, to simplify this operation, we’ve introduced a retention_time
column in the workflow_execution
table.
For existing workflow executions, the retention time will be automatically set if it was previously configured in the workflow execution options. The retention time is expected to be specified in seconds. If it was mistakenly configured in milliseconds, you may encounter a Postgres error when casting the retention time to an integer.
If you run into this issue, you can manually run the migration while specifying the correct retention time for your workflow executions.
Other noteworthy changes
Changes to medusa start
The medusa start
command is intended to be used for production envionments. Therefore, the NODE_ENV
now defaults to production
instead of development
.
New Divider component
The Divider
component has been added to the UI library.
Added Metadata forms
Metadata forms have been added for the Product Collection and Order pages.
Features
- feat(core-flows, dashboard, link-modules,medusa, types, utils): fulfillment shipping changes by @fPolic in #10902
- feat: Add tasks orchestrator by @thetutlage in #11161
- Feat/index sync data by @adrien2p in #11169
- feat: Revamp payment provider interface by @sradevski in #11015
- feat(medusa): add sku to variant query params by @riqwan in #11151
- feat(orchestration): hydrate resultset by @carlos-r-l-rodrigues in #11263
- feat: make AbstractModuleService create method type-safe by @thetutlage in #11216
- feat(core-flows): cart complete shipping validate by @fPolic in #10984
- feat: map container types for core services to interface by @thetutlage in #11295
- feat(index): full sync operations by @adrien2p in #11178
- feat(ui,dashboard): Migrate SC tables to DataTable by @kasperkristensen in #11106
- feat(ui,dashboard): Move Divider component to UI package by @kasperkristensen in #11357
Bugs
- fix(js-sdk,admin-bundler): Fix qs import by @kasperkristensen in #11172
- fix(dashboard): Matching product profile with shipping profile by @olivermrbl in #11183
- fix(dashboard): semibold font by @fPolic in #11182
- fix: exit process with a status code when build fails by @thetutlage in #11206
- fix: always load .env file alongside the environment specific file by @thetutlage in #11188
- fix: Add missing typings around creating a payment method by @sradevski in #11209
- fix(medusa): use correct request / response types by @shahednasser in #11170
- fix(order): add data model name in define schema by @shahednasser in #11181
- fix(dashboard): Allow admins to update default Sales Channel and Stock Location by @kasperkristensen in #11196
- fix: issues with peer dependencies by @thetutlage in #11272
- fix(dashboard,core-flows,types,medusa): Allow editing Order metadata by @kasperkristensen in #11285
- fix(ui): Prevent Command from triggering while a editable field has focus by @kasperkristensen in #11254
- fix: Use the correct currency for edit promotions form by @sradevski in #11307
- fix(medusa, types): fix promotion HTTP types in cart by @shahednasser in #11304
- fix(ui,types): Add Metadata form for collection by @kasperkristensen in #11300
- fix(core-flows): shipping profile update by @fPolic in #11322
- fix(dashboard): Ensure conditional prices are assigned to region by @kasperkristensen in #11335
- fix(cli): If NODE_ENV is not defined then default to production for
medusa start
by @kasperkristensen in #11325 - fix(test): update flaky fulfillment test by @fPolic in #11312
- fix(dashboard): Remove wrongful import of utils function by @kasperkristensen in #11338
- fix:(dashboard) pending difference rounding on order details page by @fPolic in #11336
- fix(utils): add static identifier to AbstractNotificationProviderService by @shahednasser in #11344
- fix(core-flows): Fix broken import of MedusaError by @kasperkristensen in #11362
- fix(admin-vite-plugin,icons,ui,dashboard): Upgrade vitest in all packages and align Vite version by @kasperkristensen in #11361
- fix: Minor fixes and cleanup to the payments setup by @sradevski in #11356
- fix(core-flows): variants update unsets prices by @fPolic in #11349
Documentation
- docs: add documentation for DataTable by @shahednasser in #11095
- docs: update links to MikroORM docs following update by @shahednasser in #11096
- docs: added plugins documentation by @shahednasser in #10989
- docs: generate references manually for 2.4.0 by @shahednasser in #11171
- docs-util: fix issue with creating StoreProductType OAS schema by @shahednasser in #11180
- docs: fix tables design + update icons package by @shahednasser in #11184
- docs: add section in update chapter for plugin projects by @shahednasser in #11185
- docs: fix sidebar navigation in API reference by @shahednasser in #11179
- docs: add section on plugin keywords by @shahednasser in #11187
- docs: change retentionTime from milliseconds to seconds by @shahednasser in #11207
- docs: fix incorrect path in schedule syncing brands chapter by @shahednasser in #11198
- docs: update b2b recipe by @shahednasser in #11213
- docs: improve AI Assistant by @shahednasser in #11208
- docs: fix overflowing content on small devices by @shahednasser in #11219
- docs: documet support for type aliases by @shahednasser in #11117
- docs: fix incorrect hook details shown by @shahednasser in #11225
- docs: changes to AI assistant icon + add button to code blocks by @shahednasser in #11227
- docs: set max width in assistant by @shahednasser in #11231
- docs: small design fixes by @shahednasser in #11243
- docs: fixes and improvements to testing docs by @shahednasser in #11244
- docs: update tanstack query version by @shahednasser in #11246
- docs: add link from installation to update guide by @shahednasser in #11245
- docs: fix typo in sales channel links docs by @shahednasser in #11268
- docs: fix link to sales channel docs by @shahednasser in #11267
- docs: fix link to promotion actions by @shahednasser in #11271
- docs: document onesided one-to-one relationship by @shahednasser in #11270
- docs: update railway deployment docs by @shahednasser in #11274
- docs: fix description of update cart OAS by @shahednasser in #11278
- docs: add troubleshooting for admin optimizeDeps by @shahednasser in #11282
- docs: document variant inventory conceptual guide by @shahednasser in #11280
- docs: add storefront guide select customer address during checkout by @shahednasser in #11288
- docs: document Query Context by @shahednasser in #11289
- docs: fix metadata destructure in query.graph by @shahednasser in #11294
- docs: fix import of defineMiddleware by @shahednasser in #11293
- docs: add util to generate clean markdown for a file by @shahednasser in #11303
- docs: add clean markdown version of all documentation pages by @shahednasser in #11308
- docs: document admin environment variables by @shahednasser in #11313
- docs: add generator for llms-full.txt by @shahednasser in #11323
- docs: clarify steps for medusa build by @shahednasser in #11324
- docs: fix appending index.html.md to api reference links by @shahednasser in #11327
- docs: update text in LLM editors section by @shahednasser in #11329
- docs: add ui to llms-full.txt by @shahednasser in #11328
- docs: added custom item price guide by @shahednasser in #11240
- docs: fix empty return in references by @shahednasser in #11343
- docs: add railway troubleshooting for host by @shahednasser in #11346
- docs: update llms.txt by @shahednasser in #11347
- docs: generate OAS after cart promotion fixes by @shahednasser in #11351
- docs: update intro of custom item price by @shahednasser in #11358
- docs: document module providers in plugins by @shahednasser in #11360
- docs: added authentication in integration tests by @shahednasser in #11363
- docs: add help dropdown by @shahednasser in #11364
- docs: fix some index.html.md links resulting 404 by @shahednasser in #11379
- docs: fix path to modules in plugin by @shahednasser in #11387
Chores
- chore(index): config changes by @carlos-r-l-rodrigues in #11121
- chore(js-sdk): Remove create user method from SDK by @olivermrbl in #11186
- chore(orchestration): validate PK when throwIfKeyNotFound by @carlos-r-l-rodrigues in #11190
- chore(core-flows,types): update TSDocs following latest payment changes by @shahednasser in #11241
- chore(ui,dashboard): Use
radix-ui
package by @kasperkristensen in #11195 - chore(medusa): clear workflow execution by @carlos-r-l-rodrigues in #11200
- chore(framework): add example of admin's vite configurations by @shahednasser in #11283
- chore(types): add @Version to new payment provider methods by @shahednasser in #11316
- chore(core-flows): update the TSDocs of new steps by @shahednasser in #11315
- chore(types): add TSDocs for retentionTime by @shahednasser in #11345
- chore: Remove unused payment method token model by @sradevski in #11342
Other Changes
- feat(dashboard): add arabic translation by @zaaakher in #11174
- Made variants.options fields optional in StoreGetProductsParams by @ikku47 in #10712
- fix: delay in event emit by @jaykanjia in #10603
- fix(order): add fulfillment labels query key on create shipment page by @Kadphol in #9792
- feat: add Greek translations by @jimrarras in #11211
- fix(create-medusa-app): --db-url keep asking db credentials by @Gederooney in #11037
- fix: complete cart workflow by @jaykanjia in #10780
- fix(admin-ui): update Turkish translations by @epaprat in #11250
- docs: fix typo in installation page.mdx by @Ishrathh in #11372
- fix(ui): add missing use client directives by @pnodet in #11368
New Contributors
- @zaaakher made their first contribution in #11174
- @ikku47 made their first contribution in #10712
- @jaykanjia made their first contribution in #10603
- @Kadphol made their first contribution in #9792
- @jimrarras made their first contribution in #11211
- @Gederooney made their first contribution in #11037
- @epaprat made their first contribution in #11250
- @Ishrathh made their first contribution in #11372
Full Changelog: v2.4.0...v2.5.0