Skip to content

Commit

Permalink
add boilerplate payment webhook handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
peelar committed Jun 28, 2024
1 parent 26b6e68 commit 3522fe6
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 35 deletions.
92 changes: 92 additions & 0 deletions src/pages/api/webhooks/payment-gateway-initialize-session.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { SaleorSyncWebhook } from "@saleor/app-sdk/handlers/next";
import { gql } from "urql";
import { PaymentGatewayInitializeSessionWebhookPayloadFragment } from "../../../../generated/graphql";
import { createClient } from "../../../lib/create-graphq-client";
import { saleorApp } from "../../../saleor-app";

/**
* Example payload of the webhook. It will be transformed with graphql-codegen to Typescript type: PaymentGatewayInitializeSessionWebhookPayloadFragment
*/
const PaymentGatewayInitializeSessionWebhookPayload = gql`
fragment PaymentGatewayInitializeSessionWebhookPayload on PaymentGatewayInitializeSession {
amount
}
`;

/**
* Top-level webhook subscription query, that will be attached to the Manifest.
* Saleor will use it to register webhook.
*/
const PaymentGatewayInitializeSession = gql`
# Payload fragment must be included in the root query
${PaymentGatewayInitializeSessionWebhookPayload}
subscription PaymentGatewayInitializeSession {
event {
...PaymentGatewayInitializeSessionWebhookPayload
}
}
`;

/**
* Create abstract Webhook. It decorates handler and performs security checks under the hood.
*
* paymentGatewayInitializeSessionWebhook.getWebhookManifest() must be called in api/manifest too!
*/
export const paymentGatewayInitializeSessionWebhook =
new SaleorSyncWebhook<PaymentGatewayInitializeSessionWebhookPayloadFragment>({
name: "Payment Gateway Initialize Session",
webhookPath: "api/webhooks/payment-gateway-initialize-session",
event: "PAYMENT_GATEWAY_INITIALIZE_SESSION",
apl: saleorApp.apl,
query: PaymentGatewayInitializeSession,
});

/**
* Export decorated Next.js handler, which adds extra context
*/
export default paymentGatewayInitializeSessionWebhook.createHandler((req, res, ctx) => {
const {
/**
* Access payload from Saleor - defined above
*/
payload,
/**
* Saleor event that triggers the webhook (here - ORDER_CREATED)
*/
event,
/**
* App's URL
*/
baseUrl,
/**
* Auth data (from APL) - contains token and saleorApiUrl that can be used to construct graphQL client
*/
authData,
} = ctx;

/**
* Create GraphQL client to interact with Saleor API.
*/
const client = createClient(authData.saleorApiUrl, async () => ({ token: authData.token }));

/**
* Now you can fetch additional data using urql.
* https://formidable.com/open-source/urql/docs/api/core/#clientquery
*/

// const data = await client.query().toPromise()

/**
* Inform Saleor that webhook was delivered properly.
*/
return res.status(200).end();
});

/**
* Disable body parser for this endpoint, so signature can be verified
*/
export const config = {
api: {
bodyParser: false,
},
};
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
import { SaleorSyncWebhook } from "@saleor/app-sdk/handlers/next";
import { gql } from "urql";
import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next";
import { OrderCreatedWebhookPayloadFragment } from "../../../../generated/graphql";
import { saleorApp } from "../../../saleor-app";
import { TransactionInitializeWebhookPayloadFragment } from "../../../../generated/graphql";
import { createClient } from "../../../lib/create-graphq-client";
import { saleorApp } from "../../../saleor-app";

/**
* Example payload of the webhook. It will be transformed with graphql-codegen to Typescript type: OrderCreatedWebhookPayloadFragment
* Example payload of the webhook. It will be transformed with graphql-codegen to Typescript type: TransactionInitializeWebhookPayloadFragment
*/
const OrderCreatedWebhookPayload = gql`
fragment OrderCreatedWebhookPayload on OrderCreated {
order {
userEmail
id
number
user {
email
firstName
lastName
}
const TransactionInitializeWebhookPayload = gql`
fragment TransactionInitializeWebhookPayload on TransactionInitializeSession {
action {
amount
currency
}
}
`;
Expand All @@ -26,33 +20,34 @@ const OrderCreatedWebhookPayload = gql`
* Top-level webhook subscription query, that will be attached to the Manifest.
* Saleor will use it to register webhook.
*/
const OrderCreatedGraphqlSubscription = gql`
const TransactionInitializeSession = gql`
# Payload fragment must be included in the root query
${OrderCreatedWebhookPayload}
subscription OrderCreated {
${TransactionInitializeWebhookPayload}
subscription TransactionInitializeSession {
event {
...OrderCreatedWebhookPayload
...TransactionInitializeWebhookPayload
}
}
`;

/**
* Create abstract Webhook. It decorates handler and performs security checks under the hood.
*
* orderCreatedWebhook.getWebhookManifest() must be called in api/manifest too!
* transactionInitializeWebhook.getWebhookManifest() must be called in api/manifest too!
*/
export const orderCreatedWebhook = new SaleorAsyncWebhook<OrderCreatedWebhookPayloadFragment>({
name: "Order Created in Saleor",
webhookPath: "api/webhooks/order-created",
event: "ORDER_CREATED",
apl: saleorApp.apl,
query: OrderCreatedGraphqlSubscription,
});
export const transactionInitializeWebhook =
new SaleorSyncWebhook<TransactionInitializeWebhookPayloadFragment>({
name: "Transaction Initialize Session",
webhookPath: "api/webhooks/transaction-initialize-session",
event: "TRANSACTION_INITIALIZE_SESSION",
apl: saleorApp.apl,
query: TransactionInitializeSession,
});

/**
* Export decorated Next.js handler, which adds extra context
*/
export default orderCreatedWebhook.createHandler((req, res, ctx) => {
export default transactionInitializeWebhook.createHandler((req, res, ctx) => {
const {
/**
* Access payload from Saleor - defined above
Expand All @@ -72,21 +67,16 @@ export default orderCreatedWebhook.createHandler((req, res, ctx) => {
authData,
} = ctx;

/**
* Perform logic based on Saleor Event payload
*/
console.log(`Order was created for customer: ${payload.order?.userEmail}`);

/**
* Create GraphQL client to interact with Saleor API.
*/
const client = createClient(authData.saleorApiUrl, async () => ({ token: authData.token }));

/**
* Now you can fetch additional data using urql.
* https://formidable.com/open-source/urql/docs/api/core/#clientquery
*/

// const data = await client.query().toPromise()

/**
Expand Down

0 comments on commit 3522fe6

Please sign in to comment.