feat(payment): sync plans and add coins rules

This commit is contained in:
2026-06-29 14:11:50 +08:00
parent 274fe87ced
commit e372d58b4c
24 changed files with 1099 additions and 224 deletions
+69 -10
View File
@@ -7,8 +7,9 @@ import type { PaymentEvent } from "./payment-events";
import { initialState, type PaymentState } from "./payment-state";
import {
createPaymentOrderActor,
loadPaymentPlansActor,
loadCachedPaymentPlansActor,
pollPaymentOrderStatusActor,
refreshPaymentPlansActor,
} from "./payment-machine.actors";
import {
defaultAutoRenewForPlan,
@@ -29,7 +30,8 @@ export const paymentMachine = setup({
events: {} as PaymentEvent,
},
actors: {
loadPlans: loadPaymentPlansActor,
loadCachedPlans: loadCachedPaymentPlansActor,
refreshPlans: refreshPaymentPlansActor,
createOrder: createPaymentOrderActor,
pollOrderStatus: pollPaymentOrderStatusActor,
},
@@ -41,13 +43,42 @@ export const paymentMachine = setup({
states: {
idle: {
on: {
PaymentInit: "loadingPlans",
PaymentInit: "loadingCachedPlans",
},
},
loadingCachedPlans: {
invoke: {
src: "loadCachedPlans",
onDone: [
{
guard: ({ event }) => (event.output?.plans.length ?? 0) > 0,
target: "refreshingPlans",
actions: assign(({ context, event }) => {
const plans = event.output?.plans ?? [];
const selectedPlanId =
context.selectedPlanId || getDefaultPlanId(plans);
return {
plans,
selectedPlanId,
autoRenew: defaultAutoRenewForPlan(selectedPlanId, plans),
errorMessage: null,
};
}),
},
{
target: "loadingPlans",
},
],
onError: {
target: "loadingPlans",
},
},
},
loadingPlans: {
invoke: {
src: "loadPlans",
src: "refreshPlans",
onDone: {
target: "ready",
actions: assign(({ context, event }) => {
@@ -57,7 +88,35 @@ export const paymentMachine = setup({
return {
plans,
selectedPlanId,
autoRenew: defaultAutoRenewForPlan(selectedPlanId),
autoRenew: defaultAutoRenewForPlan(selectedPlanId, plans),
errorMessage: null,
};
}),
},
onError: {
target: "ready",
actions: assign(({ event }) => ({
errorMessage: toPaymentErrorMessage(event.error),
})),
},
},
},
refreshingPlans: {
invoke: {
src: "refreshPlans",
onDone: {
target: "ready",
actions: assign(({ context, event }) => {
const plans = event.output.plans;
const selectedPlanId =
plans.some((plan) => plan.planId === context.selectedPlanId)
? context.selectedPlanId
: getDefaultPlanId(plans);
return {
plans,
selectedPlanId,
autoRenew: defaultAutoRenewForPlan(selectedPlanId, plans),
errorMessage: null,
};
}),
@@ -73,12 +132,12 @@ export const paymentMachine = setup({
ready: {
on: {
PaymentInit: "loadingPlans",
PaymentInit: "refreshingPlans",
PaymentPlanSelected: {
actions: assign(({ event }) => ({
actions: assign(({ context, event }) => ({
...resetOrderState(),
selectedPlanId: event.planId,
autoRenew: defaultAutoRenewForPlan(event.planId),
autoRenew: defaultAutoRenewForPlan(event.planId, context.plans),
})),
},
PaymentPayChannelChanged: {
@@ -208,10 +267,10 @@ export const paymentMachine = setup({
on: {
PaymentPlanSelected: {
target: "ready",
actions: assign(({ event }) => ({
actions: assign(({ context, event }) => ({
...resetOrderState(),
selectedPlanId: event.planId,
autoRenew: defaultAutoRenewForPlan(event.planId),
autoRenew: defaultAutoRenewForPlan(event.planId, context.plans),
})),
},
PaymentPayChannelChanged: {