From 47f9e9ebdeececc1cd29f323cfd77fa43939bdc1 Mon Sep 17 00:00:00 2001 From: Puspal Paul Date: Sun, 9 Feb 2025 15:03:35 +0530 Subject: [PATCH 1/2] Integrate Payeezy --- 42-cent-payeezy/README.md | 81 +++++++++++++++++++++ 42-cent-payeezy/index.js | 137 +++++++++++++++++++++++++++++++++++ 42-cent-payeezy/package.json | 27 +++++++ 3 files changed, 245 insertions(+) create mode 100644 42-cent-payeezy/README.md create mode 100644 42-cent-payeezy/index.js create mode 100644 42-cent-payeezy/package.json diff --git a/42-cent-payeezy/README.md b/42-cent-payeezy/README.md new file mode 100644 index 0000000..40c697c --- /dev/null +++ b/42-cent-payeezy/README.md @@ -0,0 +1,81 @@ +# 42-cent-payeezy + +Payeezy adapter for [42-cent](https://github.com/continuous-software/42-cent) payment processing library. + +## Installation + +```bash +npm install 42-cent-payeezy --save +``` + +## Usage + +```javascript +const Gateways = require('42-cent'); +const PayeezyGateway = require('42-cent-payeezy'); + +// Register the Payeezy gateway +Gateways.registerGateway('Payeezy', PayeezyGateway.factory); + +// Create a new gateway instance +const gateway = Gateways.use('Payeezy', { + apiKey: 'your-api-key', + apiSecret: 'your-api-secret', + merchantToken: 'your-merchant-token', + environment: 'sandbox' // or 'production' +}); + +// Create a credit card +const creditCard = Gateways.createCreditCard({ + cardNumber: '4111111111111111', + expirationMonth: '01', + expirationYear: '2025', + cvv: '123', + cardHolder: 'John Doe' +}); + +// Create a prospect (customer) +const prospect = Gateways.createProspect({ + firstName: 'John', + lastName: 'Doe', + address1: '123 Main St', + city: 'New York', + state: 'NY', + zip: '10001', + country: 'US' +}); + +// Process a payment +gateway.submitTransaction({ + amount: 10.00, + currency: 'USD', + orderId: 'order-123' +}, creditCard, prospect) + .then(transaction => { + console.log('Transaction successful:', transaction); + }) + .catch(error => { + console.error('Transaction failed:', error); + }); +``` + +## API Reference + +### Gateway Configuration + +The gateway requires the following configuration options: + +- `apiKey`: Your Payeezy API key +- `apiSecret`: Your Payeezy API secret +- `merchantToken`: Your Payeezy merchant token +- `environment`: Either 'sandbox' or 'production' (default: 'sandbox') + +### Methods + +- `submitTransaction(order, creditCard, prospect)`: Process a payment +- `refundTransaction(transactionId, options)`: Refund a transaction +- `voidTransaction(transactionId, options)`: Void a transaction + +## License + +MIT diff --git a/42-cent-payeezy/index.js b/42-cent-payeezy/index.js new file mode 100644 index 0000000..a2f57dc --- /dev/null +++ b/42-cent-payeezy/index.js @@ -0,0 +1,137 @@ +'use strict'; + +const BaseGateway = require('42-cent-base').BaseGateway; +const CreditCard = require('42-cent-model').CreditCard; +const Prospect = require('42-cent-model').Prospect; +const Promise = require('bluebird'); +const _ = require('lodash'); +const crypto = require('crypto'); + +class PayeezyGateway extends BaseGateway { + constructor(options) { + super(); + this.apiKey = options.apiKey; + this.apiSecret = options.apiSecret; + this.merchantToken = options.merchantToken; + this.environment = options.environment || 'sandbox'; + this.baseUrl = this.environment === 'sandbox' + ? 'https://api-cert.payeezy.com/v1' + : 'https://api.payeezy.com/v1'; + } + + generateHmac(payload, timestamp) { + const message = this.apiKey + timestamp + this.merchantToken + JSON.stringify(payload); + return crypto + .createHmac('sha256', this.apiSecret) + .update(message) + .digest('hex'); + } + + async submitTransaction(transaction) { + const timestamp = new Date().getTime(); + const hmac = this.generateHmac(transaction, timestamp); + + const headers = { + 'Content-Type': 'application/json', + 'apikey': this.apiKey, + 'token': this.merchantToken, + 'timestamp': timestamp, + 'hmac': hmac + }; + + try { + const response = await fetch(`${this.baseUrl}/transactions`, { + method: 'POST', + headers: headers, + body: JSON.stringify(transaction) + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + return this.createTransactionResponse(data); + } catch (error) { + throw new Error(`Failed to process transaction: ${error.message}`); + } + } + + createTransactionResponse(response) { + return { + transactionId: response.transaction_id, + _original: response, + authCode: response.authorization_num, + status: response.transaction_status + }; + } + + submitTransaction(order, creditCard, prospect, other) { + const payload = { + merchant_ref: order.orderId || Date.now().toString(), + transaction_type: 'purchase', + method: 'credit_card', + amount: order.amount, + currency_code: order.currency || 'USD', + credit_card: { + type: this.getCardType(creditCard.cardNumber), + cardholder_name: creditCard.cardHolder, + card_number: creditCard.cardNumber, + exp_date: creditCard.expirationMonth.toString().padStart(2, '0') + creditCard.expirationYear.toString().slice(-2), + cvv: creditCard.cvv + } + }; + + if (prospect) { + payload.billing_address = { + name: prospect.firstName + ' ' + prospect.lastName, + street: prospect.address1, + city: prospect.city, + state_province: prospect.state, + zip_postal_code: prospect.zip, + country: prospect.country || 'US' + }; + } + + return this.submitTransaction(payload); + } + + getCardType(number) { + // Basic card type detection + if (/^4/.test(number)) return 'visa'; + if (/^5[1-5]/.test(number)) return 'mastercard'; + if (/^3[47]/.test(number)) return 'amex'; + if (/^6(?:011|5)/.test(number)) return 'discover'; + return 'unknown'; + } + + refundTransaction(transactionId, options) { + const payload = { + merchant_ref: options.orderId || Date.now().toString(), + transaction_type: 'refund', + method: 'credit_card', + amount: options.amount, + currency_code: options.currency || 'USD', + transaction_tag: options.transactionTag, + transaction_id: transactionId + }; + + return this.submitTransaction(payload); + } + + voidTransaction(transactionId, options) { + const payload = { + merchant_ref: options.orderId || Date.now().toString(), + transaction_type: 'void', + method: 'credit_card', + transaction_tag: options.transactionTag, + transaction_id: transactionId + }; + + return this.submitTransaction(payload); + } +} + +exports.factory = function (options) { + return new PayeezyGateway(options); +}; diff --git a/42-cent-payeezy/package.json b/42-cent-payeezy/package.json new file mode 100644 index 0000000..fddf12c --- /dev/null +++ b/42-cent-payeezy/package.json @@ -0,0 +1,27 @@ +{ + "name": "42-cent-payeezy", + "version": "1.0.0", + "description": "Payeezy adapter for 42-cent", + "main": "index.js", + "scripts": { + "test": "mocha test" + }, + "keywords": [ + "42-cent", + "payment", + "gateway", + "payeezy" + ], + "author": "", + "license": "MIT", + "dependencies": { + "42-cent-base": "^1.0.0", + "42-cent-model": "^2.0.0", + "bluebird": "^3.7.2", + "lodash": "^4.17.21" + }, + "devDependencies": { + "chai": "^4.3.4", + "mocha": "^9.1.3" + } +} From b60a02fcd81f1cc81ab0c3f906cd059ac017278c Mon Sep 17 00:00:00 2001 From: Puspal Paul Date: Sun, 9 Feb 2025 15:12:33 +0530 Subject: [PATCH 2/2] Modified --- 42-cent-payeezy/README.md | 81 ------------------- 42-cent-payeezy/package.json | 27 ------- README.md | 27 +++++++ index.js | 2 + .../index.js => lib/PayeezyGateway.js | 0 package.json | 3 +- 6 files changed, 31 insertions(+), 109 deletions(-) delete mode 100644 42-cent-payeezy/README.md delete mode 100644 42-cent-payeezy/package.json rename 42-cent-payeezy/index.js => lib/PayeezyGateway.js (100%) diff --git a/42-cent-payeezy/README.md b/42-cent-payeezy/README.md deleted file mode 100644 index 40c697c..0000000 --- a/42-cent-payeezy/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# 42-cent-payeezy - -Payeezy adapter for [42-cent](https://github.com/continuous-software/42-cent) payment processing library. - -## Installation - -```bash -npm install 42-cent-payeezy --save -``` - -## Usage - -```javascript -const Gateways = require('42-cent'); -const PayeezyGateway = require('42-cent-payeezy'); - -// Register the Payeezy gateway -Gateways.registerGateway('Payeezy', PayeezyGateway.factory); - -// Create a new gateway instance -const gateway = Gateways.use('Payeezy', { - apiKey: 'your-api-key', - apiSecret: 'your-api-secret', - merchantToken: 'your-merchant-token', - environment: 'sandbox' // or 'production' -}); - -// Create a credit card -const creditCard = Gateways.createCreditCard({ - cardNumber: '4111111111111111', - expirationMonth: '01', - expirationYear: '2025', - cvv: '123', - cardHolder: 'John Doe' -}); - -// Create a prospect (customer) -const prospect = Gateways.createProspect({ - firstName: 'John', - lastName: 'Doe', - address1: '123 Main St', - city: 'New York', - state: 'NY', - zip: '10001', - country: 'US' -}); - -// Process a payment -gateway.submitTransaction({ - amount: 10.00, - currency: 'USD', - orderId: 'order-123' -}, creditCard, prospect) - .then(transaction => { - console.log('Transaction successful:', transaction); - }) - .catch(error => { - console.error('Transaction failed:', error); - }); -``` - -## API Reference - -### Gateway Configuration - -The gateway requires the following configuration options: - -- `apiKey`: Your Payeezy API key -- `apiSecret`: Your Payeezy API secret -- `merchantToken`: Your Payeezy merchant token -- `environment`: Either 'sandbox' or 'production' (default: 'sandbox') - -### Methods - -- `submitTransaction(order, creditCard, prospect)`: Process a payment -- `refundTransaction(transactionId, options)`: Refund a transaction -- `voidTransaction(transactionId, options)`: Void a transaction - -## License - -MIT diff --git a/42-cent-payeezy/package.json b/42-cent-payeezy/package.json deleted file mode 100644 index fddf12c..0000000 --- a/42-cent-payeezy/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "42-cent-payeezy", - "version": "1.0.0", - "description": "Payeezy adapter for 42-cent", - "main": "index.js", - "scripts": { - "test": "mocha test" - }, - "keywords": [ - "42-cent", - "payment", - "gateway", - "payeezy" - ], - "author": "", - "license": "MIT", - "dependencies": { - "42-cent-base": "^1.0.0", - "42-cent-model": "^2.0.0", - "bluebird": "^3.7.2", - "lodash": "^4.17.21" - }, - "devDependencies": { - "chai": "^4.3.4", - "mocha": "^9.1.3" - } -} diff --git a/README.md b/README.md index 5bbdf8e..392c9f2 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,14 @@ You can see the API the gateway intends to fulfill by looking at the [BaseGatewa **Note:** All builds are run daily thanks to [Travis CI cron jobs](https://docs.travis-ci.com/user/cron-jobs/). +- Omise +- Stripe +- Braintree +- PayPal +- WorldPay +- Beanstream +- Payeezy + [![Build Status](https://travis-ci.org/continuous-software/42-cent-braintree.svg?branch=master)](https://travis-ci.org/continuous-software/42-cent-braintree) [Braintree](https://github.com/continuous-software/42-cent-braintree) [![Build Status](https://travis-ci.org/continuous-software/42-cent-omise.svg?branch=master)](https://travis-ci.org/continuous-software/42-cent-omise) [Omise](https://github.com/continuous-software/42-cent-omise) [![Build Status](https://travis-ci.org/continuous-software/42-cent-stripe.svg?branch=master)](https://travis-ci.org/continuous-software/42-cent-stripe) [Stripe](https://github.com/continuous-software/42-cent-stripe) @@ -52,3 +60,22 @@ Feel free to go and fix things if you can. [![Build Status](https://travis-ci.org/continuous-software/node-payflow.svg?branch=master)](https://travis-ci.org/continuous-software/node-payflow) [Payflow](https://github.com/continuous-software/node-payflow) [![Build Status](https://travis-ci.org/continuous-software/node-rocketgate.svg?branch=master)](https://travis-ci.org/continuous-software/node-rocketgate) [RocketGate](https://github.com/continuous-software/node-rocketgate) [![Build Status](https://travis-ci.org/continuous-software/node-virtualmerchant.svg?branch=master)](https://travis-ci.org/continuous-software/node-virtualmerchant) [VirtualMerchant](https://github.com/continuous-software/node-virtualmerchant) + +## Gateway Specific Configuration + +### Payeezy + +```javascript +var client = Gateways.use('Payeezy', { + apiKey: 'your-api-key', + apiSecret: 'your-api-secret', + merchantToken: 'your-merchant-token', + environment: 'sandbox' // or 'production' +}); +``` + +Required configuration: +- `apiKey`: Your Payeezy API key +- `apiSecret`: Your Payeezy API secret +- `merchantToken`: Your Payeezy merchant token +- `environment`: Either 'sandbox' or 'production' (default: 'sandbox') diff --git a/index.js b/index.js index df325c4..78dd125 100644 --- a/index.js +++ b/index.js @@ -7,6 +7,7 @@ var PayPal = require('42-cent-paypal').factory; var WorldPay = require('42-cent-worldpay').factory; var Beanstream = require('42-cent-beanstream').factory; var Moneris = require('42-cent-moneris'); +var Payeezy = require('./lib/PayeezyGateway').factory; // Deprecated: // var AuthorizeNet = require('authorize-net'); @@ -22,6 +23,7 @@ var supportedGateway = { "PayPal": PayPal, "WorldPay": WorldPay, "Beanstream": Beanstream, + "Payeezy": Payeezy, // "Authorize.Net": AuthorizeNet, // "PayFlow": PayFlow, // "RocketGate": RocketGate, diff --git a/42-cent-payeezy/index.js b/lib/PayeezyGateway.js similarity index 100% rename from 42-cent-payeezy/index.js rename to lib/PayeezyGateway.js diff --git a/package.json b/package.json index 8e5ce54..ad8f14f 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,8 @@ "nmi": "^1.0.3", "payflow": "^1.0.0", "rocketgate": "^1.0.0", - "virtualmerchant": "^1.0.0" + "virtualmerchant": "^1.0.0", + "42-cent-payeezy": "^1.0.0" }, "devDependencies": { "mocha": "^1.21.4"