feat: add boilerplate for order_refunded

This commit is contained in:
Adrian Pilarczyk 2023-08-22 14:26:54 +02:00
parent 6e084a67e4
commit 542bdcaa84
7 changed files with 112 additions and 4 deletions

View file

@ -0,0 +1,29 @@
fragment OrderRefundedSubscription on Order {
id
avataxId: metafield(key: "avataxId")
channel {
id
slug
}
}
fragment OrderRefundedEventSubscription on Event {
__typename
... on OrderRefunded {
order {
...OrderRefundedSubscription
}
recipient {
privateMetadata {
key
value
}
}
}
}
subscription OrderRefundedSubscription {
event {
...OrderRefundedEventSubscription
}
}

View file

@ -1,14 +1,18 @@
import { AuthData } from "@saleor/app-sdk/APL"; import { AuthData } from "@saleor/app-sdk/APL";
import { OrderConfirmedSubscriptionFragment, TaxBaseFragment } from "../../../generated/graphql"; import {
OrderConfirmedSubscriptionFragment,
OrderRefundedSubscriptionFragment,
} from "../../../generated/graphql";
import { Logger, createLogger } from "../../lib/logger"; import { Logger, createLogger } from "../../lib/logger";
import { CalculateTaxesPayload } from "../../pages/api/webhooks/checkout-calculate-taxes";
import { OrderCancelledPayload } from "../../pages/api/webhooks/order-cancelled"; import { OrderCancelledPayload } from "../../pages/api/webhooks/order-cancelled";
import { OrderRefundedPayload } from "../../pages/api/webhooks/order-refunded";
import { ProviderWebhookService } from "../taxes/tax-provider-webhook"; import { ProviderWebhookService } from "../taxes/tax-provider-webhook";
import { AvataxClient } from "./avatax-client"; import { AvataxClient } from "./avatax-client";
import { AvataxConfig, defaultAvataxConfig } from "./avatax-connection-schema"; import { AvataxConfig, defaultAvataxConfig } from "./avatax-connection-schema";
import { AvataxCalculateTaxesAdapter } from "./calculate-taxes/avatax-calculate-taxes-adapter"; import { AvataxCalculateTaxesAdapter } from "./calculate-taxes/avatax-calculate-taxes-adapter";
import { AvataxOrderCancelledAdapter } from "./order-cancelled/avatax-order-cancelled-adapter"; import { AvataxOrderCancelledAdapter } from "./order-cancelled/avatax-order-cancelled-adapter";
import { AvataxOrderConfirmedAdapter } from "./order-confirmed/avatax-order-confirmed-adapter"; import { AvataxOrderConfirmedAdapter } from "./order-confirmed/avatax-order-confirmed-adapter";
import { CalculateTaxesPayload } from "../../pages/api/webhooks/checkout-calculate-taxes";
export class AvataxWebhookService implements ProviderWebhookService { export class AvataxWebhookService implements ProviderWebhookService {
config = defaultAvataxConfig; config = defaultAvataxConfig;
@ -24,6 +28,7 @@ export class AvataxWebhookService implements ProviderWebhookService {
}); });
const avataxClient = new AvataxClient(config); const avataxClient = new AvataxClient(config);
refundOrder: (payload: OrderRefundedSubscriptionFragment) => Promise<void>;
this.config = config; this.config = config;
this.client = avataxClient; this.client = avataxClient;
} }
@ -49,4 +54,8 @@ export class AvataxWebhookService implements ProviderWebhookService {
await adapter.send(payload); await adapter.send(payload);
} }
async refundOrder(payload: OrderRefundedPayload) {
// todo: implement
}
} }

View file

@ -7,6 +7,7 @@ import {
import { Logger, createLogger } from "../../lib/logger"; import { Logger, createLogger } from "../../lib/logger";
import { OrderCancelledPayload } from "../../pages/api/webhooks/order-cancelled"; import { OrderCancelledPayload } from "../../pages/api/webhooks/order-cancelled";
import { OrderRefundedPayload } from "../../pages/api/webhooks/order-refunded";
import { getAppConfig } from "../app/get-app-config"; import { getAppConfig } from "../app/get-app-config";
import { AvataxWebhookService } from "../avatax/avatax-webhook.service"; import { AvataxWebhookService } from "../avatax/avatax-webhook.service";
import { ProviderConnection } from "../provider-connections/provider-connections"; import { ProviderConnection } from "../provider-connections/provider-connections";
@ -57,7 +58,11 @@ class ActiveTaxProviderService implements ProviderWebhookService {
} }
async cancelOrder(payload: OrderCancelledPayload) { async cancelOrder(payload: OrderCancelledPayload) {
this.client.cancelOrder(payload); return this.client.cancelOrder(payload);
}
async refundOrder(payload: OrderRefundedPayload) {
return this.client.refundOrder(payload);
} }
} }

View file

@ -2,6 +2,7 @@ import { SyncWebhookResponsesMap } from "@saleor/app-sdk/handlers/next";
import { OrderConfirmedSubscriptionFragment } from "../../../generated/graphql"; import { OrderConfirmedSubscriptionFragment } from "../../../generated/graphql";
import { CalculateTaxesPayload } from "../../pages/api/webhooks/checkout-calculate-taxes"; import { CalculateTaxesPayload } from "../../pages/api/webhooks/checkout-calculate-taxes";
import { OrderCancelledPayload } from "../../pages/api/webhooks/order-cancelled"; import { OrderCancelledPayload } from "../../pages/api/webhooks/order-cancelled";
import { OrderRefundedPayload } from "../../pages/api/webhooks/order-refunded";
export type CalculateTaxesResponse = SyncWebhookResponsesMap["ORDER_CALCULATE_TAXES"]; export type CalculateTaxesResponse = SyncWebhookResponsesMap["ORDER_CALCULATE_TAXES"];
@ -11,4 +12,5 @@ export interface ProviderWebhookService {
calculateTaxes: (payload: CalculateTaxesPayload) => Promise<CalculateTaxesResponse>; calculateTaxes: (payload: CalculateTaxesPayload) => Promise<CalculateTaxesResponse>;
confirmOrder: (payload: OrderConfirmedSubscriptionFragment) => Promise<CreateOrderResponse>; confirmOrder: (payload: OrderConfirmedSubscriptionFragment) => Promise<CreateOrderResponse>;
cancelOrder: (payload: OrderCancelledPayload) => Promise<void>; cancelOrder: (payload: OrderCancelledPayload) => Promise<void>;
refundOrder: (payload: OrderRefundedPayload) => Promise<void>;
} }

View file

@ -5,6 +5,7 @@ import {
} from "../../../generated/graphql"; } from "../../../generated/graphql";
import { Logger, createLogger } from "../../lib/logger"; import { Logger, createLogger } from "../../lib/logger";
import { CalculateTaxesPayload } from "../../pages/api/webhooks/checkout-calculate-taxes"; import { CalculateTaxesPayload } from "../../pages/api/webhooks/checkout-calculate-taxes";
import { OrderRefundedPayload } from "../../pages/api/webhooks/order-refunded";
import { ProviderWebhookService } from "../taxes/tax-provider-webhook"; import { ProviderWebhookService } from "../taxes/tax-provider-webhook";
import { TaxJarCalculateTaxesAdapter } from "./calculate-taxes/taxjar-calculate-taxes-adapter"; import { TaxJarCalculateTaxesAdapter } from "./calculate-taxes/taxjar-calculate-taxes-adapter";
import { TaxJarOrderConfirmedAdapter } from "./order-confirmed/taxjar-order-confirmed-adapter"; import { TaxJarOrderConfirmedAdapter } from "./order-confirmed/taxjar-order-confirmed-adapter";
@ -46,6 +47,10 @@ export class TaxJarWebhookService implements ProviderWebhookService {
} }
async cancelOrder(payload: OrderCancelledEventSubscriptionFragment) { async cancelOrder(payload: OrderCancelledEventSubscriptionFragment) {
// TaxJar isn't implemented yet // todo: implement
}
async refundOrder(payload: OrderRefundedPayload) {
// todo: implement
} }
} }

View file

@ -7,6 +7,7 @@ import { orderCalculateTaxesSyncWebhook } from "./webhooks/order-calculate-taxes
import { orderConfirmedAsyncWebhook } from "./webhooks/order-confirmed"; import { orderConfirmedAsyncWebhook } from "./webhooks/order-confirmed";
import { REQUIRED_SALEOR_VERSION } from "../../../saleor-app"; import { REQUIRED_SALEOR_VERSION } from "../../../saleor-app";
import { orderCancelledAsyncWebhook } from "./webhooks/order-cancelled"; import { orderCancelledAsyncWebhook } from "./webhooks/order-cancelled";
import { orderRefundedAsyncWebhook } from "./webhooks/order-refunded";
export default createManifestHandler({ export default createManifestHandler({
async manifestFactory({ appBaseUrl }) { async manifestFactory({ appBaseUrl }) {
@ -37,6 +38,7 @@ export default createManifestHandler({
checkoutCalculateTaxesSyncWebhook.getWebhookManifest(apiBaseURL), checkoutCalculateTaxesSyncWebhook.getWebhookManifest(apiBaseURL),
orderConfirmedAsyncWebhook.getWebhookManifest(apiBaseURL), orderConfirmedAsyncWebhook.getWebhookManifest(apiBaseURL),
orderCancelledAsyncWebhook.getWebhookManifest(apiBaseURL), orderCancelledAsyncWebhook.getWebhookManifest(apiBaseURL),
orderRefundedAsyncWebhook.getWebhookManifest(apiBaseURL),
], ],
}; };

View file

@ -0,0 +1,56 @@
import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next";
import {
OrderRefundedEventSubscriptionFragment,
UntypedOrderRefundedSubscriptionDocument,
} from "../../../../generated/graphql";
import { saleorApp } from "../../../../saleor-app";
import { createLogger } from "../../../lib/logger";
import { getActiveConnectionService } from "../../../modules/taxes/get-active-connection-service";
import { WebhookResponse } from "../../../modules/app/webhook-response";
export const config = {
api: {
bodyParser: false,
},
};
export type OrderRefundedPayload = Extract<
OrderRefundedEventSubscriptionFragment,
{ __typename: "OrderRefunded" }
>;
export const orderRefundedAsyncWebhook = new SaleorAsyncWebhook<OrderRefundedPayload>({
name: "OrderRefunded",
apl: saleorApp.apl,
event: "ORDER_REFUNDED",
query: UntypedOrderRefundedSubscriptionDocument,
webhookPath: "/api/webhooks/order-refunded",
});
export default orderRefundedAsyncWebhook.createHandler(async (req, res, ctx) => {
const logger = createLogger({ event: ctx.event });
const { payload } = ctx;
const webhookResponse = new WebhookResponse(res);
logger.info("Handler called with payload");
if (!payload.order) {
return webhookResponse.error(new Error("Insufficient order data"));
}
try {
const appMetadata = payload.recipient?.privateMetadata ?? [];
const channelSlug = payload.order.channel.slug;
const taxProvider = getActiveConnectionService(channelSlug, appMetadata, ctx.authData);
logger.info("Refunding order...");
await taxProvider.refundOrder(payload);
logger.info("Order refunded");
return webhookResponse.success();
} catch (error) {
return webhookResponse.error(new Error("Error while refunding tax provider order"));
}
});