Skip to content

Commit

Permalink
feat(payment): support create pending payment
Browse files Browse the repository at this point in the history
  • Loading branch information
silenaker committed Nov 11, 2024
1 parent 29aea3f commit 29e896f
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"

export interface CreatePaymentSessionStepInput {
payment_collection_id: string
provider_id: string
provider_id?: string
provider_token?: string
amount?: BigNumberInput
context?: PaymentProviderContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { createPaymentSessionStep } from "../steps"

export interface CreatePaymentSessionsWorkflowInput {
payment_collection_id: string
provider_id: string
provider_id?: string
provider_token?: string
amount?: BigNumberInput
context?: PaymentProviderContext
Expand Down
2 changes: 1 addition & 1 deletion packages/core/types/src/http/payment/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ export interface BasePaymentSession {
/**
* The ID of the associated payment provider.
*/
provider_id: string
provider_id: string | null

/**
* The data necessary for the payment provider to process the payment session.
Expand Down
2 changes: 1 addition & 1 deletion packages/core/types/src/payment/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ export interface PaymentSessionDTO {
/**
* The ID of the associated payment provider.
*/
provider_id: string
provider_id: string | null

/**
* The data necessary for the payment provider to process the payment session.
Expand Down
7 changes: 6 additions & 1 deletion packages/core/types/src/payment/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ export interface CreatePaymentSessionDTO {
/**
* The provider's ID.
*/
provider_id: string
provider_id?: string | null

/**
* The provider's payment method token
Expand Down Expand Up @@ -258,6 +258,11 @@ export interface UpdatePaymentSessionDTO {
*/
id: string

/**
* The provider's ID.
*/
provider_id?: string | null

/**
* The provider's payment method token
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Migration } from "@mikro-orm/migrations"

export class Migration20240902113510 extends Migration {
export class Migration20241106090002 extends Migration {
async up(): Promise<void> {
this.addSql(
'alter table if exists "capture" add column if not exists "data" jsonb not null;'
Expand All @@ -14,6 +14,9 @@ export class Migration20240902113510 extends Migration {
this.addSql(
'alter table if exists "payment_session" drop constraint if exists "payment_session_status_check";'
)
this.addSql(
'alter table if exists "payment_session" alter column "provider_id" drop not null;'
)
}

async down(): Promise<void> {
Expand Down
4 changes: 2 additions & 2 deletions packages/modules/payment/src/models/payment-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export default class PaymentSession {
})
raw_amount: BigNumberRawValue

@Property({ columnType: "text" })
provider_id: string
@Property({ columnType: "text", nullable: true })
provider_id: string | null = null

@Property({ columnType: "jsonb" })
data: Record<string, unknown> = {}
Expand Down
170 changes: 119 additions & 51 deletions packages/modules/payment/src/services/payment-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,24 +345,32 @@ export default class PaymentModuleService
sharedContext
)

try {
res = await this.paymentProviderService_.createSession(data.provider_id, {
amount,
currency_code: paymentCollection.currency_code,
context: { ...data.context, session_id: paymentSession.id },
token: data.provider_token,
})
} catch (err) {
await this.paymentSessionService_.delete(paymentSession.id, sharedContext)
throw err
}
if (data.provider_id) {
try {
res = await this.paymentProviderService_.createSession(
data.provider_id,
{
amount,
currency_code: paymentCollection.currency_code,
context: { ...data.context, session_id: paymentSession.id },
token: data.provider_token,
}
)
} catch (err) {
await this.paymentSessionService_.delete(
paymentSession.id,
sharedContext
)
throw err
}

await this.handleProviderSessionResponse_(res, sharedContext)
paymentSession = await this.paymentSessionService_.retrieve(
paymentSession.id,
{},
sharedContext
)
await this.handleProviderSessionResponse_(res, sharedContext)
paymentSession = await this.paymentSessionService_.retrieve(
paymentSession.id,
{},
sharedContext
)
}

return this.baseRepository_.serialize(paymentSession, { populate: true })
}
Expand All @@ -372,35 +380,79 @@ export default class PaymentModuleService
data: UpdatePaymentSessionDTO,
@MedusaContext() sharedContext?: Context
): Promise<PaymentSessionDTO> {
const session = await this.paymentSessionService_.retrieve(data.id, {
select: [
"id",
"data",
"context",
"provider_id",
"metadata",
"currency_code",
"raw_amount",
],
})
let res: PaymentProviderSessionResponse | undefined

if (
!data.amount &&
!data.context &&
!data.provider_token &&
!data.metadata
data.provider_id &&
session.provider_id &&
data.provider_id !== session.provider_id
) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`The payment session update requires at least an amount, context, provider token or metadata.`
res = await this.paymentProviderService_.cancelPayment(
session.provider_id,
session.data
)
}

const session = await this.paymentSessionService_.retrieve(data.id, {
select: ["id", "data", "context", "provider_id", "metadata"],
})
if (
data.provider_id &&
(!session.provider_id || data.provider_id !== session.provider_id)
) {
try {
res = await this.paymentProviderService_.createSession(
data.provider_id,
{
amount: data.amount ?? session.raw_amount,
currency_code: session.currency_code,
context: {
...session.context,
...data.context,
session_id: session.id,
},
token: data.provider_token,
}
)
} catch (err) {
if (res) {
await this.handleProviderSessionResponse_(res, sharedContext)
}
throw err
}
} else if (session.provider_id) {
res = await this.paymentProviderService_.updateSession(
session.provider_id,
{
data: session.data,
context: {
...session.context,
...data.context,
session_id: session.id,
},
amount: data.amount,
token: data.provider_token,
}
)
}

await this.handleProviderSessionResponse_(
await this.paymentProviderService_.updateSession(session.provider_id, {
data: session.data,
context: {
...session.context,
...data.context,
session_id: session.id,
},
amount: data.amount,
token: data.provider_token,
}),
sharedContext
)
if (res) {
if (data.provider_id && data.provider_id !== session.provider_id) {
await this.paymentSessionService_.update(
{ id: session.id, provider_id: data.provider_id },
sharedContext
)
}
await this.handleProviderSessionResponse_(res, sharedContext)
}

if (data.amount || data.context || data.metadata) {
const toUpdate: any = {}
Expand Down Expand Up @@ -430,10 +482,12 @@ export default class PaymentModuleService
sharedContext
)

await this.paymentProviderService_.deleteSession(
session.provider_id,
session.data
)
if (session.provider_id) {
await this.paymentProviderService_.deleteSession(
session.provider_id,
session.data
)
}

await this.paymentSessionService_.delete(id, sharedContext)
}
Expand All @@ -450,6 +504,13 @@ export default class PaymentModuleService
sharedContext
)

if (!paymentSession.provider_id) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`The payment session has not yet specified a provider.`
)
}

await this.handleProviderSessionResponse_(
await this.paymentProviderService_.authorizePayment(
paymentSession.provider_id,
Expand Down Expand Up @@ -549,13 +610,20 @@ export default class PaymentModuleService
sharedContext
)

await this.handleProviderSessionResponse_(
await this.paymentProviderService_.cancelPayment(
paymentSession.provider_id,
paymentSession.data
),
sharedContext
)
if (paymentSession.provider_id) {
await this.handleProviderSessionResponse_(
await this.paymentProviderService_.cancelPayment(
paymentSession.provider_id,
paymentSession.data
),
sharedContext
)
} else {
await this.paymentSessionService_.update(
{ id, status: PaymentSessionStatus.CANCELED },
sharedContext
)
}

return this.retrievePaymentSession(id, {}, sharedContext)
}
Expand Down

0 comments on commit 29e896f

Please sign in to comment.