Skip to content

Commit 9475fab

Browse files
committed
Add apis'
1 parent debc00c commit 9475fab

14 files changed

+643
-26
lines changed

.env-example

+7
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,12 @@ NEXT_PUBLIC_WORDPRESS_SITE_URL=https://example.com
44
#Frontend Next.js Site URL
55
NEXT_PUBLIC_SITE_URL=http://localhost:3000
66

7+
#Stripe env variables.
8+
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_xxx
9+
STRIPE_SECRET_KEY=sk_test_xxx
10+
11+
STRIPE_WEBHOOK_ENDPOINT_SECRET=whsec_xxxx
12+
13+
## WooCommerce Consumer Key and secret.
714
WC_CONSUMER_KEY=ck_xx
815
WC_CONSUMER_SECRET=cs_xx

package-lock.json

+64
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+4
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,21 @@
99
"svg": "svgr -d src/components/icons src/components/icons/svgs"
1010
},
1111
"dependencies": {
12+
"@stripe/stripe-js": "^1.36.0",
1213
"@svgr/cli": "^5.5.0",
1314
"@woocommerce/woocommerce-rest-api": "^1.0.1",
1415
"axios": "^0.21.1",
1516
"classnames": "^2.3.1",
1617
"dompurify": "^2.3.1",
1718
"lodash": "^4.17.21",
19+
"micro": "^9.4.1",
1820
"next": "11.1.0",
21+
"next-stripe": "^1.0.0-beta.9",
1922
"prop-types": "^15.7.2",
2023
"react": "17.0.2",
2124
"react-dom": "17.0.2",
2225
"sass": "^1.38.0",
26+
"stripe": "^10.8.0",
2327
"validator": "^13.7.0"
2428
},
2529
"devDependencies": {

pages/api/create-order.js

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
const WooCommerceRestApi = require( '@woocommerce/woocommerce-rest-api' ).default;
2+
import { isEmpty } from 'lodash';
3+
4+
const api = new WooCommerceRestApi( {
5+
url: process.env.NEXT_PUBLIC_WORDPRESS_SITE_URL,
6+
consumerKey: process.env.WC_CONSUMER_KEY,
7+
consumerSecret: process.env.WC_CONSUMER_SECRET,
8+
version: "wc/v3"
9+
} );
10+
11+
/**
12+
* Create order endpoint.
13+
*
14+
* @see http://woocommerce.github.io/woocommerce-rest-api-docs/?javascript#create-an-order
15+
*
16+
* @param {Object} req Request.
17+
* @param {Object} res Response.
18+
*
19+
* @return {Promise<{orderId: string, success: boolean, error: string}>}
20+
*/
21+
export default async function handler( req, res ) {
22+
23+
const responseData = {
24+
success: false,
25+
orderId: '',
26+
total: '',
27+
currency: '',
28+
error: '',
29+
};
30+
31+
if ( isEmpty( req.body ) ) {
32+
responseData.error = 'Required data not sent';
33+
return responseData;
34+
}
35+
36+
const data = req.body;
37+
data.status = 'pending';
38+
data.set_paid = false;
39+
40+
try {
41+
const { data } = await api.post(
42+
'orders',
43+
req.body,
44+
);
45+
46+
responseData.success = true;
47+
responseData.orderId = data.number;
48+
responseData.total = data.total;
49+
responseData.currency = data.currency;
50+
51+
res.json( responseData );
52+
53+
} catch ( error ) {
54+
console.log( 'error', error );
55+
/**
56+
* Request usually fails if the data in req.body is not sent in the format required.
57+
*
58+
* @see Data shape expected: https://stackoverflow.com/questions/49349396/create-an-order-with-coupon-lines-in-woocomerce-rest-api
59+
*/
60+
responseData.error = error.message;
61+
res.status( 500 ).json( responseData );
62+
}
63+
}

pages/api/get-stripe-session.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const stripe = require( 'stripe' )( process.env.STRIPE_SECRET_KEY );
2+
3+
module.exports = async ( req, res ) => {
4+
5+
const { session_id } = req.query;
6+
7+
const session = await stripe.checkout.sessions.retrieve( session_id );
8+
9+
res.status( 200 ).json( session );
10+
};

pages/api/stripe-web-hook.js

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { buffer } from "micro";
2+
const Stripe = require('stripe');
3+
const WooCommerceRestApi = require("@woocommerce/woocommerce-rest-api").default;
4+
5+
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
6+
apiVersion: '2020-08-27'
7+
});
8+
const webhookSecret = process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET;
9+
10+
export const config = {
11+
api: {
12+
bodyParser: false,
13+
},
14+
};
15+
16+
const api = new WooCommerceRestApi({
17+
url: process.env.NEXT_PUBLIC_WORDPRESS_SITE_URL,
18+
consumerKey: process.env.WC_CONSUMER_KEY,
19+
consumerSecret: process.env.WC_CONSUMER_SECRET,
20+
version: "wc/v3"
21+
});
22+
23+
/**
24+
* Update Order.
25+
*
26+
* Once payment is successful or failed,
27+
* Update Order Status to 'Processing' or 'Failed' and set the transaction id.
28+
*
29+
* @param {String} newStatus Order Status to be updated.
30+
* @param {String} orderId Order id
31+
* @param {String} transactionId Transaction id.
32+
*
33+
* @returns {Promise<void>}
34+
*/
35+
const updateOrder = async ( newStatus, orderId, transactionId = '' ) => {
36+
37+
let newOrderData = {
38+
status: newStatus
39+
}
40+
41+
if ( transactionId ) {
42+
newOrderData.transaction_id = transactionId
43+
}
44+
45+
try {
46+
const {data} = await api.put( `orders/${ orderId }`, newOrderData );
47+
console.log( '✅ Order updated data', data );
48+
} catch (ex) {
49+
console.error('Order creation error', ex);
50+
throw ex;
51+
}
52+
}
53+
54+
const handler = async (req, res) => {
55+
if (req.method === "POST") {
56+
const buf = await buffer(req);
57+
const sig = req.headers["stripe-signature"];
58+
59+
let stripeEvent;
60+
61+
try {
62+
stripeEvent = stripe.webhooks.constructEvent(buf, sig, webhookSecret);
63+
console.log( 'stripeEvent', stripeEvent );
64+
} catch (err) {
65+
res.status(400).send(`Webhook Error: ${err.message}`);
66+
return;
67+
}
68+
69+
if ( 'checkout.session.completed' === stripeEvent.type ) {
70+
const session = stripeEvent.data.object;
71+
console.log( 'sessionsession', session );
72+
console.log( '✅ session.metadata.orderId', session.metadata.orderId, session.id );
73+
// Payment Success.
74+
try {
75+
await updateOrder( 'processing', session.metadata.orderId, session.id );
76+
} catch (error) {
77+
await updateOrder( 'failed', session.metadata.orderId );
78+
console.error('Update order error', error);
79+
}
80+
}
81+
82+
res.json({ received: true });
83+
} else {
84+
res.setHeader("Allow", "POST");
85+
res.status(405).end("Method Not Allowed");
86+
}
87+
};
88+
89+
export default handler;

pages/api/stripe/[...nextstripe].js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import NextStripe from 'next-stripe'
2+
3+
export default NextStripe({
4+
stripe_key: process.env.STRIPE_SECRET_KEY
5+
})

0 commit comments

Comments
 (0)