-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
251 lines (220 loc) · 7.61 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
// General config
require('dotenv').config()
const express = require('express');
const cors = require('cors');
const CryptoAccount = require("send-crypto");
var axios = require('axios');
var CryptoJS = require("crypto-js");
const PORT = process.env.PORT || 5000;
const app = express();
// Rapyd request setup
const httpMethod = 'post'; // Should always be lower case (not POST)
const baseURL = 'https://sandboxapi.rapyd.net';
const urlPath = '/v1/checkout';
const fullRapydURL = baseURL + urlPath;
const salt = CryptoJS.lib.WordArray.random(12);
const timestamp = (Math.floor(new Date().getTime() / 1000) - 10).toString();
const accessKey = "235FCE21EB935EEE0FA0";
const secretKey = "d840d232c1e029f9b186266c34d04b82cbc34765e446d330e8c507fca107872b95ed1fba1fc33fca";
// For reference purposes:
var body = {
// 'amount': 99.99, // Remove 'amount' property if you provide a 'cart_items' prop.
'country': 'US',
'currency': 'USD',
'complete_checkout_url': 'http://localhost:3000/success',
'cart_items': [
{
'name': 'Cinnamon Arabic Beans',
'amount': 35,
'image': 'https://firebasestorage.googleapis.com/v0/b/skill-evolution-3e59c.appspot.com/o/coffee2.jpeg?alt=media&token=c211afce-4d93-4aa6-bc70-0f9eeaf5ece6',
'quantity': 1
}
]
}
// Setting up Rapyd signature before making requests.
const signatureKey = httpMethod + urlPath + salt + timestamp + accessKey + secretKey + JSON.stringify(body);
let signature = CryptoJS.enc.Hex.stringify(CryptoJS.HmacSHA256(signatureKey, secretKey));
signature = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(signature));
// Uncomment to test if your env vars are set up correctly:
// console.log(urlPath)
// console.log(accessKey)
// console.log(secretKey)
// Middlewares
app.use(cors());
app.use(express.json());
// Routes
app.get('/process-payment', async (req, res) => {
// Props: paymentCurrency, amount, pk (private key)
console.log(req.body);
const paymentCurrency = req.body.paymentCurrency;
const amount = req.body.amount;
const pk = req.body.pk;
// Processing cryptocurrency payments
if (paymentCurrency === 'BTC' || paymentCurrency === 'ETH') {
// Loading account from private key
const account = new CryptoAccount(pk);
// Transferring funds
try {
await account
.send(process.env.SELLING_CRYPTO_ACCOUNT, amount, paymentCurrency)
// Just to make sure everything went alright...
.on('transactionHash', console.log)
.on('confirmation', console.log);
res.send({ success: true });
} catch(error) {
// An error occurred, such as:
// Insufficient funds from wallet
// Invalid private key
// (...)
res.send({ success: false });
}
}else {
// Payment using native currency (e.g. USD, EUR, BRL, etc)
const url = await processRapydPayment(req.body);
console.log(url)
res.send({ url });
}
});
const processRapydPayment = (xxx) => {
// *** Sample body WITH a shopping cart:
// {
// 'country': 'US',
// 'currency': 'USD',
// 'complete_checkout_url': 'https://google.com',
// 'cart_items': [
// {
// 'name': 'that naaaaame',
// 'amount': 19.12,
// 'image': 'STATIC_FILE_ADDRESS',
// 'quantity': 1
// }
// ]
// }
// *** Sample body WITHOUT a shopping cart:
// {
// 'amount': 99.99, // Remove 'amount' property if you provide a 'cart_items' prop.
// 'country': 'US',
// 'currency': 'USD',
// 'complete_checkout_url': 'https://google.com'
// }
// Creating a special Axios instance to add custom request headers.
const instance = axios.create({
headers: {
'access_key': accessKey,
'content-Type': 'application/json',
'salt': salt,
'signature': signature,
'timestamp': timestamp
}
});
// Stringifying our request body
if (JSON.stringify(body) !== '{}' && body !== '') {
reqBody = JSON.stringify(body);
}
instance.post(fullRapydURL, body)
.then(res => {
return res.data.data.redirect_url;
})
.catch(error => {
console.log('An error occurred!');
console.log(error);
})
.then(() => {
// Equivalent to finally{} (It's always executed).
})
}
app.get('/disburse', async (req, res) => {
// Props: bankAccount, transferAmount, walletSender (valid rapyd wallet)
console.log(req.body);
// Comment the following and uncomment the other one
var bankAccount = "BG96611020345678";
var transferAmount = "2";
var walletSender = "ewallet_dfc659569155e576aad8d8cc334ed22e";
// Uncomment to use data from the request
//var transferAmount = req.body .transferAmount;
//var bankAccount = req.body.bankAccount;
//var walletSender = req.body.walletSender;
// Data of the person receiving the money from the store wallet
// @ATTENTION: Actual sensitive data omitted from repository since it includes
// client/business name, bank, and card information.
var receiver = {
"name":"Nathan Wilk",
"address": "123 Nathan Mauricio Street",
"email": "Nathan@Mauricio.winners",
"country": "US",
"city": "Orlando",
"postcode": "33333",
"account_number": bankAccount , // Bank account number from the input
"bank_name": "US General Bank", // Bank Name, should I just leave the default ones?
"state": "FL",
"identification_type": "SSC", // Bank data stuff. I would rather not touch these lmao
"identification_value": "123456789",
"bic_swift": "BUINBGSF",
"ach_code": "123456789"
};
// Data Object of the person sending the money
var sender = {
"name":"Nathan Wilk 2",
"address": "123 Nathan Mauricio Street",
"city": "Orlando",
"state": "FL",
"date_of_birth": "29/07/2001", // NOTE! DD/MM/YYYY (Took some debugging to fix this lol)
"postcode": "33333",
"phonenumber": "9999999999",
"remitter_account_type": "Individual",
"source_of_income": "salary",
"identification_type": "License No", // I feel like we should just use the demo stuff here
"identification_value": "123456789",
"purpose_code": "ABCDEFGHI",
"account_number": "123456789",
"beneficiary_relationship": "client" // The "store" is sending money to the owner
}
// Body request
var data = JSON.stringify({
"beneficiary": receiver,
"beneficiary_country": "US",
"beneficiary_entity_type": "individual",
"description": "Payout - Transfer from Store to Bank Account",
"merchant_reference_id": "GHY-0YU-HUJ-POI",
"ewallet": walletSender, // MUST BE A VALID Rapyd Wallet
"payout_amount": transferAmount, // Amount to Transfer as a string!
"payout_currency": "USD",
"payout_method_type": "us_general_bank",
"sender": sender,
"sender_country": "US",
"sender_currency": "USD",
"sender_entity_type": "individual",
"statement_descriptor": "GHY* Limited Access 800-123-4567",
"metadata": {
"merchant_defined": true
}
});
let url = baseURL + '/v1/payouts';
let the_salt = CryptoJS.lib.WordArray.random(12);
let the_time = (Math.floor(new Date().getTime() / 1000) - 10).toString();
let signed = httpMethod + url + the_salt + the_time + accessKey + secretKey + JSON.stringify(data);
let le_sign = CryptoJS.enc.Hex.stringify(CryptoJS.HmacSHA256(signed, secretKey));
le_sign = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(le_sign));
var config = {
method: 'post',
url: 'https://sandboxapi.rapyd.net/v1/payouts',
headers: {
'Content-Type': 'application/json',
'access_key': accessKey,
'salt': the_salt,
'timestamp': the_time,
'signature': le_sign
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
});
app.listen(PORT, () => {
console.log(`The server is listening on port ${PORT}`);
});