const crypto = require("crypto")
// The `generateKeyPairSync` method accepts two arguments:
// 1. The type ok keys we want, which in this case is "rsa"
// 2. An object with the properties of the key
const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
// The standard secure default length for RSA keys is 2048 bits
modulusLength: 2048,
})
// use the public and private keys
// ...
Encryption
// This is the data we want to encrypt
const data = "my secret data"
const encryptedData = crypto.publicEncrypt(
{
key: publicKey,
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
oaepHash: "sha256",
},
// We convert the data string to a buffer using `Buffer.from`
Buffer.from(data)
)
// The encrypted data is in the form of bytes, so we print it in base64 format
// so that it's displayed in a more readable form
console.log("encypted data: ", encryptedData.toString("base64"))
Decryption
const decryptedData = crypto.privateDecrypt(
{
key: privateKey,
// In order to decrypt the data, we need to specify the
// same hashing function and padding scheme that we used to
// encrypt the data in the previous step
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
oaepHash: "sha256",
},
encryptedData
)
// The decrypted data is of the Buffer type, which we can convert to a
// string to reveal the original data
console.log("decrypted data: ", decryptedData.toString())
This hash method was developed in late 2015, and has not seen widespread use yet. Its algorithm is unrelated to the one used by its predecessor, SHA-2.
The SHA3-256 algorithm is a variant with equivalent applicability to that of the earlier SHA-256, with the former taking slightly longer to calculate than the later.
'use strict';
const fs = require('fs');
let buff = fs.readFileSync('stack-abuse-logo.png');
let base64data = buff.toString('base64');
console.log('Image converted to base 64 is:nn' + base64data);
Base64 Strings to Binary Data
The reverse process here is very similar to how we decode Base64 strings, as we saw in an earlier section. The biggest difference is the output destination and how data is written there. Let’s see the example:
'use strict';
const fs = require('fs');
let data = 'iVBORw0KGgoAAAANSUhEUgAAABkAAAATCAYAAABlcqYFAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAA' +
'CA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAABWWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0' +
'YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly' +
'93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAg' +
'ICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZm' +
'Y6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpMwidZAAADuUlEQVQ4EbVU' +
'TUtcZxR+7ufkXp1SZ4iZRE1EDVQRnTAhowsZMFm40I2rNqUIIev8hvoPQroQXBTqwiAWcd0EglEhiZNajVZrQGXAWAzaZpzMnZn7lXPeeIe5Da' +
'Wb9Ax33vOec8/znI/3vVI6nfbxP4v8b/iSJIGfzyGfkPi+D13XUalUBL6qqmIvy5+8WuX/r2RCkUzAoIuLi2hqaoLrutjb28P6+josyxJkiqJA' +
'07SQXiqVwHaOZYx/itLc3Px9YIxEIlheXsbExATGxsYwMjIiwEdHRwXA/Pw8EokEcrkcDg4OYJomVlZWMDU1JSqfmZlBR0cHbNsOtVoNCHjlTF' +
'iSySQMwxAVxONxQbi0tIRMJoPe3l5MT0+jtbUVg4ODYGImY18qlcL4+DhisZjoggCjv1C7uOyenh7Mzs5iY2ND6FQpdnd3sba2JloSjUYxPDyM' +
'/v5+TE5OYn9/X9jZtrOzg+3t7WqyAUmoEu419/+HBw9E+eVymbJqAJP39fWBCR3HEU+hUMDQ0JCYGc8um81iYGAAjY2N8DwvwBdraCY8tHhDA1' +
'Y3N9Hd3S2yvH37O7RcbsF7AuUsD9+8wdOFBTx/8QJtbW1C5/nMzc3R0D2UyxXk83lRXcAk1V5GCT5sSUGDbeHxy9/EO98M9OOXzT9wfHISxKC1' +
'vR0GHfOtrS2g/SouWwU0Xkggu7qO9PUkJFULnbIQyTm6ewu2hF+vnOIIUQwdGlg8f4QF6wvMWBq+pAkaskSnx4FFVUf0CNpcC797KizXQ4oAHh' +
'VdXJJ81F7j6kwUynPHlXDPdFB2fRj+KVK0KvT2rbp3uKYryJU11Cke8qqMuOoioeeJ1MPDYxM36m1cNSq4GdFx58RAWvbx8TrXnK4IgR16Em5G' +
'K4iqHi5GHHxLgcSDn97WgZPoND+GGZRpPYH85cgiiRQl1ltXxmFFQ5PuopP8TrW5ZyRcWp7AbmkeZefg5+N6PPnbRJdpw/YlfB0vQiPQZwVdZN' +
'tFZEVK6D1VTnccJlXzuqTjvOZiq6Rhj2KqLSJsofOHgIl8+t0/qsfDioxmSUWGjrRFzhYi/5Oynrdl3KXHIZDXtF6hil8R6I9FBV/RvDLnXKxS' +
'bAdVYhNeINXBMwmXWCTQGG2Y+Jj+dFrfEmiMAtmeowpo9ojTvkD+A/L1UJUMmiVfkuz6WTyZhFRJAgP33j3bsM5k/Fng68UP21hYJyyxZwLWuS' +
'2cKMfUSm3rhD0g4E2g197fwMZ+Bgt8rNe2iP2BhL5dgfFzrx8AfECEDdx45a0AAAAASUVORK5CYII=';
let buff = new Buffer(data, 'base64');
fs.writeFileSync('stack-abuse-logo-out.png', buff);
console.log('Base64 image data converted to file: stack-abuse-logo-out.png');
There are several ways to test your webhook endpoint:
Create test activity on your account
Manually send test events from the Dashboard
Use the Stripe CLI
이렇게 있는데 cli 를 이용하는 것이 가장 간단하다. 실제 stripe에 설정한 webhook과는 무관하게 모든 webhook을 테스트 할수 있다. 단순히 내 server(webhook event를 받아들일)작업만 해 놓으면 바로 확인 가능하다.
stripe cli 설치
brew install stripe/stripe-cli/stripe
stripe 연결
stripe login
Your pairing code is: humour-nifty-finer-magic
Press Enter to open up the browser (^C to quit)
내서버에서 오는 결과를 보여줄 터미얼에 아래와 같이 입력
stripe listen --forward-to localhost:5000/hooks
Ready! Your webhook signing secret is '{{WEBHOOK_SIGNING_SECRET}}' (^C to quit)
내서버에 webhook event를 전달하는 명령어를 위와는 다른 터미널에 아래와 같이 입력
stripe trigger payment_intent.created
그러면 아래와 같이 결과가 나온다
.
.
.
.
내 개발자 서버로 오는 webhook event가 맞는 것인지 확인을 위해서는
stripe에서 오는 key (Stripe-Signature header 안에 들어 있음) 를 내 서버에 있는 endpointSecret (stripe CLI에서 stripe login 입력하면 나오는 키값, stripe 웹사이트 계정페이지에서 signing secret으로 표기된 키값)을 비교한다.
// Set your secret key. Remember to switch to your live secret key in production!
// See your keys here: https://dashboard.stripe.com/account/apikeys
const stripe = require('stripe')('sk_test_51HsFV3EpgfvwVVPojh8CroIb788ovjYa3fB04FcVPs7EpnLwxihHzuO85R9p5b3H6qULpSyZu0432qvnovTPrKpe00NLL0RJne');
// If you are testing your webhook locally with the Stripe CLI you
// can find the endpoint's secret by running `stripe listen`
// Otherwise, find your endpoint's secret in your webhook settings in the Developer Dashboard
const endpointSecret = 'whsec_...';
// This example uses Express to receive webhooks
const app = require('express')();
// Use body-parser to retrieve the raw body as a buffer
const bodyParser = require('body-parser');
// Match the raw body to content type application/json
app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => {
const sig = request.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret);
}
catch (err) {
response.status(400).send(`Webhook Error: ${err.message}`);
}
// Handle the event
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
console.log('PaymentIntent was successful!');
break;
case 'payment_method.attached':
const paymentMethod = event.data.object;
console.log('PaymentMethod was attached to a Customer!');
break;
// ... handle other event types
default:
console.log(`Unhandled event type ${event.type}`);
}
// Return a response to acknowledge receipt of the event
response.json({received: true});
});
app.listen(4242, () => console.log('Running on port 4242'));
단 switch구문내 const paymentIntent 는 var paymentIntent로 바꾼다.
const paymentMethod도 var paymentMethod로 수정한다. (lint error를 발생시킨다.)
When you trigger an event with the Stripe CLI, under the hood it’s making all of the requisite API methods to result in that event firing. In this case, it is creating and confirming a PaymentIntent.
To get a resulting payment_intent.succeeded event, you’ll need to create a PaymentIntent (payment_intent.created will fire for this one). Then you need to confirm the payment intent and actually collect payment (which results in: charge.created, charge.succeeded, and payment_intent.succeeded).
For other event types like checkout.session.completed, many other events will fire that represent the objects that are prerequisite to get to a valid checkout.session.completed event.
If you only want to forward the payment_intent.succeeded event locally, (and it’s a good idea when in production to enable only selected event types for your webhook endpoint), then you might want to pass the -e argument to stripe listen with the comma separated list of specific events you want to listen for. In this case you might update your listen command to: