diff --git a/.versionrc b/.versionrc index 55ee099..d522c8f 100644 --- a/.versionrc +++ b/.versionrc @@ -1,7 +1,7 @@ { "types": [ {"type": "feat", "section": "Funcionalidades"}, - {"type": "fix", "section": "Errors Corrigidos"}, + {"type": "fix", "section": "Erros Corrigidos"}, {"type": "chore", "hidden": true}, {"type": "docs", "hidden": true}, {"type": "style", "hidden": true}, diff --git a/src/class/bank-slip.ts b/src/class/bank-slip.ts index f0bfcaf..da1c104 100644 --- a/src/class/bank-slip.ts +++ b/src/class/bank-slip.ts @@ -15,12 +15,6 @@ export class BankSlip { } public create(request: BankSlipCreateRequestModel): Promise { - const options: IHttpRequestOptions = this.util.getHttpRequestOptions({ - method: HttpRequestMethodEnum.POST, - path: '/1/sales', - hostname: this.cieloTransactionParams.hostnameTransacao, - }); - - return this.util.request(options, request); + return this.util.postToSales(request); } } \ No newline at end of file diff --git a/src/class/cards.ts b/src/class/cards.ts index c41dc6c..1e02e10 100644 --- a/src/class/cards.ts +++ b/src/class/cards.ts @@ -13,11 +13,6 @@ export class Card { } public createTokenizedCard(request: TokenizeRequestModel): Promise { - const options: IHttpRequestOptions = this.util.getHttpRequestOptions({ - method: HttpRequestMethodEnum.POST, - path: '/1/card', - hostname: this.cieloTransactionParams.hostnameTransacao, - }); - return this.util.request(options, request); + return this.util.post({ path: '/1/card' }, request); } } \ No newline at end of file diff --git a/src/class/consult.ts b/src/class/consult.ts index 5be574a..08b186f 100644 --- a/src/class/consult.ts +++ b/src/class/consult.ts @@ -15,64 +15,52 @@ import { RecurrentPaymentConsultResponseModel } from '../models/recurrent-paymen export class Consult { private cieloTransactionParams: CieloTransactionInterface; + private util: Utils; + constructor(transaction: CieloTransactionInterface) { this.cieloTransactionParams = transaction; + this.util = new Utils(transaction); } public paymentId(params: ConsultTransactionPaymentIdRequestModel): Promise { - const util = new Utils(this.cieloTransactionParams); - const options: IHttpRequestOptions = util.getHttpRequestOptions({ - method: HttpRequestMethodEnum.GET, + const options = { path: `/1/sales/${params.paymentId}`, - hostname: this.cieloTransactionParams.hostnameQuery, - }); + }; - return util.request(options, {}); + return this.util.get(options); } public merchantOrderId(params: ConsultTransactionMerchantOrderIdRequestModel): Promise { - const util = new Utils(this.cieloTransactionParams); - const options: IHttpRequestOptions = util.getHttpRequestOptions({ - method: HttpRequestMethodEnum.GET, + const options = { path: `/1/sales?merchantOrderId=${params.merchantOrderId}`, - hostname: this.cieloTransactionParams.hostnameQuery, - }); + }; - return util.request(options, {}); + return this.util.get(options); } public recurrent(params: ConsultTransactionRecurrentPaymentIdRequestModel): Promise { - const util = new Utils(this.cieloTransactionParams); - const options: IHttpRequestOptions = util.getHttpRequestOptions({ - method: HttpRequestMethodEnum.GET, + const options = { path: `/1/RecurrentPayment/${params.recurrentPaymentId}`, - hostname: this.cieloTransactionParams.hostnameQuery, - }); + }; - return util.request(options, {}); + return this.util.get(options); } public bin(params: ConsultBinRequestModel): Promise { - const util = new Utils(this.cieloTransactionParams); - const options: IHttpRequestOptions = util.getHttpRequestOptions({ - method: HttpRequestMethodEnum.GET, + const options = { path: `/1/cardBin/${params.cardBin}`, - hostname: this.cieloTransactionParams.hostnameQuery, - }); + }; - return util.request(options, {}); + return this.util.get(options); } public cardtoken(params: ConsultTokenRequestModel): Promise { - const util = new Utils(this.cieloTransactionParams); - const options: IHttpRequestOptions = util.getHttpRequestOptions({ - method: HttpRequestMethodEnum.GET, + const options = { path: `/1/card/${params.cardToken}`, - hostname: this.cieloTransactionParams.hostnameQuery, - }); + }; - return util.request(options, {}); + return this.util.get(options); } } \ No newline at end of file diff --git a/src/class/creditcard.ts b/src/class/creditcard.ts index 70a0fad..91fadd3 100644 --- a/src/class/creditcard.ts +++ b/src/class/creditcard.ts @@ -19,12 +19,7 @@ export class CreditCard { } public transaction(transaction: TransactionCreditCardRequestModel): Promise { - const options: IHttpRequestOptions = this.util.getHttpRequestOptions({ - method: HttpRequestMethodEnum.POST, - path: "/1/sales", - hostname: this.cieloTransactionParams.hostnameTransacao, - }); - return this.util.request(options, transaction); + return this.util.postToSales(transaction); } public captureSaleTransaction(transaction: CaptureRequestModel): Promise { diff --git a/src/class/debit-card.ts b/src/class/debit-card.ts index c42c626..389590f 100644 --- a/src/class/debit-card.ts +++ b/src/class/debit-card.ts @@ -12,11 +12,6 @@ export class DebitCard { } public createSimpleTransaction(transaction: DebitCardSimpleTransactionRequestModel): Promise { - const options: IHttpRequestOptions = this.util.getHttpRequestOptions({ - method: HttpRequestMethodEnum.POST, - path: "/1/sales", - hostname: this.cieloTransactionParams.hostnameTransacao, - }); - return this.util.request(options, transaction); + return this.util.postToSales(transaction); } } \ No newline at end of file diff --git a/src/class/eletronic-transfer.ts b/src/class/eletronic-transfer.ts index ad6f943..0ba45a8 100644 --- a/src/class/eletronic-transfer.ts +++ b/src/class/eletronic-transfer.ts @@ -12,12 +12,6 @@ export class EletronicTransfer { } public create(request: EletronicTransferCreateRequestModel): Promise { - const options: IHttpRequestOptions = this.util.getHttpRequestOptions({ - method: HttpRequestMethodEnum.POST, - path: '/1/sales', - hostname: this.cieloTransactionParams.hostnameTransacao, - }); - - return this.util.request(options, request); + return this.util.postToSales(request); } } \ No newline at end of file diff --git a/src/class/recurrent.ts b/src/class/recurrent.ts index a1c4ca8..bba60b9 100644 --- a/src/class/recurrent.ts +++ b/src/class/recurrent.ts @@ -24,13 +24,7 @@ export class Recurrent { } public create(params: RecurrentCreateModel): Promise { - const options: IHttpRequestOptions = this.util.getHttpRequestOptions({ - method: HttpRequestMethodEnum.POST, - path: '/1/sales/', - hostname: this.cieloTransactionParams.hostnameTransacao, - }); - - return this.util.request(options, params); + return this.util.postToSales(params); } public modifyCustomer(params: RecurrentModifyCustomerModel): Promise { diff --git a/src/class/utils.ts b/src/class/utils.ts index b9bd9bc..405a5b6 100644 --- a/src/class/utils.ts +++ b/src/class/utils.ts @@ -10,6 +10,38 @@ export class Utils { this.cieloConstructor = params; } + public get(params: { path: string }): Promise { + const hostname = this.cieloConstructor.hostnameQuery; + const { path } = params; + const method = HttpRequestMethodEnum.GET; + + const options: IHttpRequestOptions = this.getHttpRequestOptions({ + path, + hostname, + method, + }); + return this.request(options, {}); + } + + public postToSales(data: U): Promise { + return this.post({ path: '/1/sales/' }, data); + } + + /** + * Realiza um post na API da Cielo + * @param params path do post + * @param data payload de envio + */ + public post(params: { path: string }, data: U):Promise { + const { path } = params; + const options: IHttpRequestOptions = this.getHttpRequestOptions({ + method: HttpRequestMethodEnum.POST, + path, + hostname: this.cieloConstructor.hostnameTransacao, + }); + return this.request(options, data); + } + public getHttpRequestOptions(params: { hostname: string, path: string, method: HttpRequestMethodEnum }): IHttpRequestOptions { return { method: params.method, @@ -53,7 +85,7 @@ export class Utils { res.on('end', () => { const response = (chunks.length > 0 && this.validateJSON(chunks)) ? JSON.parse(chunks) : ''; - if (res.statusCode && [200, 201].indexOf(res.statusCode) === -1) return reject(this.parseHttpRequestError(options, data, response)); + if (res.statusCode && [200, 201].indexOf(res.statusCode) === -1) return reject(this.parseHttpRequestError(options, data, res)); if (options.method === 'PUT' && chunks.length === 0) return resolve(this.parseHttpPutResponse(res)); return resolve({ ...this.parseHttpPutResponse(res), diff --git a/src/models/payment.request.model.ts b/src/models/payment.request.model.ts index 37b88c2..6adc916 100644 --- a/src/models/payment.request.model.ts +++ b/src/models/payment.request.model.ts @@ -35,7 +35,7 @@ export interface PaymentRequestModel { /** * Texto impresso na fatura bancaria comprador - Exclusivo para VISA/MASTER - não permite caracteres especiais - Ver Anexo */ - softDescriptor: string; + softDescriptor?: string; /** * Dados do cartão */ @@ -63,7 +63,7 @@ export interface PaymentRequestModel { /** * URI para onde o usuário será redirecionado após o fim do pagamento */ - ReturnUrl?: string; + returnUrl?: string; /** * Informações de recorrência de pagamento diff --git a/tests/recurrent.test.ts b/tests/recurrent.test.ts index 75116b4..8e0c50c 100644 --- a/tests/recurrent.test.ts +++ b/tests/recurrent.test.ts @@ -1,167 +1,262 @@ -import { EnumRecurrentPaymentInterval, EnumRecurrentPaymentUpdateInterval } from './../src/enums'; +import { + EnumRecurrentPaymentInterval, + EnumRecurrentPaymentUpdateInterval, +} from './../src/enums'; import test from 'tape'; import { - CieloConstructor, - Cielo, - RecurrentCreateModel, - RecurrentModifyIntervalModel, - RecurrentModifyCustomerModel, - RecurrentModifyAmountModel, - RecurrentModifyNextPaymentDateModel, - RecurrentModifyModel, - ConsultTransactionRecurrentPaymentIdRequestModel, + CieloConstructor, + Cielo, + RecurrentCreateModel, + RecurrentModifyIntervalModel, + RecurrentModifyCustomerModel, + RecurrentModifyAmountModel, + RecurrentModifyNextPaymentDateModel, + RecurrentModifyModel, + ConsultTransactionRecurrentPaymentIdRequestModel, } from '../src'; import { EnumCardType, EnumBrands } from '../src/enums'; const cieloParams: CieloConstructor = { - merchantId: "dbe5e423-ed15-4c27-843a-fedf325ea67c", - merchantKey: "NPGKHFARFASEZEPYEYLTXJMWACSWDEMJWBAKWPQD", - sandbox: true, + merchantId: 'dbe5e423-ed15-4c27-843a-fedf325ea67c', + merchantKey: 'NPGKHFARFASEZEPYEYLTXJMWACSWDEMJWBAKWPQD', + sandbox: true, }; const cielo = new Cielo(cieloParams); function error(err: Object) { - console.log('Ocorreu o seguinte erro', err) + console.log('Ocorreu o seguinte erro', err); } test(`Recorrencia`, async (t) => { + const createRecurrencyParams: RecurrentCreateModel = { + merchantOrderId: '2014113245231706', + customer: { + name: 'Comprador rec programada', + }, + payment: { + type: EnumCardType.CREDIT, + amount: 1500, + installments: 1, + softDescriptor: '123456789ABCD', + currency: 'BRL', + country: 'BRA', + recurrentPayment: { + authorizeNow: true, + endDate: '2022-12-01', + interval: EnumRecurrentPaymentInterval.SEMIANNUAL, + }, + creditCard: { + cardNumber: '4024007197692931', + holder: 'Teste Holder', + expirationDate: '12/2030', + securityCode: '262', + saveCard: false, + brand: 'Visa' as EnumBrands, + }, + }, + }; + + const firstRecurrency = await cielo.recurrent + .create(createRecurrencyParams) + .catch(error); + if (!firstRecurrency) { + t.end('Erro na criação da recorrência'); + return; + } + t.assert( + firstRecurrency.payment.recurrentPayment.reasonCode === 0, + 'Pagamento recorrente criado' + ); + t.assert( + firstRecurrency.payment.status === 1, + 'Status transacional autorizado (1)' + ); + t.assert( + firstRecurrency.payment.recurrentPayment.interval === 6, + 'Intervalo de recorrência correto (6)' + ); + + const modifyRecurrencyParams: RecurrentModifyIntervalModel = { + paymentId: firstRecurrency.payment.recurrentPayment.recurrentPaymentId, + interval: EnumRecurrentPaymentUpdateInterval.MONTHLY, + }; + const modifyRecurrency = await cielo.recurrent + .modifyInterval(modifyRecurrencyParams) + .catch(error); + if (modifyRecurrency) { + t.assert( + modifyRecurrency.statusCode === 200, + 'StatusCode da modificação da recorrência para mensal correto (200)' + ); + } + + const updateCustomer: RecurrentModifyCustomerModel = { + paymentId: firstRecurrency.payment.recurrentPayment.recurrentPaymentId, + customer: { + name: 'Customer', + email: 'customer@teste.com', + birthdate: '1999-12-12', + identity: '22658954236', + identityType: 'CPF', + address: { + street: 'Rua Teste', + number: '174', + complement: 'AP 201', + zipCode: '21241140', + city: 'Rio de Janeiro', + state: 'RJ', + country: 'BRA', + }, + deliveryAddress: { + street: 'Outra Rua Teste', + number: '123', + complement: 'AP 111', + zipCode: '21241111', + city: 'Qualquer Lugar', + state: 'QL', + country: 'BRA', + }, + }, + }; - const createRecurrencyParams: RecurrentCreateModel = { - merchantOrderId: '2014113245231706', - customer: { - name: 'Comprador rec programada' - }, - payment: { - type: EnumCardType.CREDIT, - amount: 1500, - installments: 1, - softDescriptor: '123456789ABCD', - currency: 'BRL', - country: 'BRA', - recurrentPayment: { - authorizeNow: true, - endDate: '2022-12-01', - interval: EnumRecurrentPaymentInterval.SEMIANNUAL - }, - creditCard: { - cardNumber: '4024007197692931', - holder: 'Teste Holder', - expirationDate: '12/2030', - securityCode: '262', - saveCard: false, - brand: 'Visa' as EnumBrands - } + const customer = await cielo.recurrent + .modifyCustomer(updateCustomer) + .catch(error); + if (customer) { + t.assert( + customer.statusCode === 200, + 'StatusCode da modificação do Customer correto (200)' + ); } - } - - const firstRecurrency = await cielo.recurrent.create(createRecurrencyParams).catch(error); - if (!firstRecurrency) { - t.end('Erro na criação da recorrência'); - return; - } - t.assert(firstRecurrency.payment.recurrentPayment.reasonCode === 0, 'Pagamento recorrente criado') - t.assert(firstRecurrency.payment.status === 1, 'Status transacional autorizado (1)') - t.assert(firstRecurrency.payment.recurrentPayment.interval === 6, 'Intervalo de recorrência correto (6)') - - const modifyRecurrencyParams: RecurrentModifyIntervalModel = { - paymentId: firstRecurrency.payment.recurrentPayment.recurrentPaymentId, - interval: EnumRecurrentPaymentUpdateInterval.MONTHLY - } - const modifyRecurrency = await cielo.recurrent.modifyInterval(modifyRecurrencyParams).catch(error) - if (modifyRecurrency) { - t.assert(modifyRecurrency.statusCode === 200, 'StatusCode da modificação da recorrência para mensal correto (200)') - } - - const updateCustomer: RecurrentModifyCustomerModel = { - paymentId: firstRecurrency.payment.recurrentPayment.recurrentPaymentId, - customer: { - name: 'Customer', - email: 'customer@teste.com', - birthdate: '1999-12-12', - identity: '22658954236', - identityType: 'CPF', - address: { - street: 'Rua Teste', - number: '174', - complement: 'AP 201', - zipCode: '21241140', - city: 'Rio de Janeiro', - state: 'RJ', - country: 'BRA' - }, - deliveryAddress: { - street: 'Outra Rua Teste', - number: '123', - complement: 'AP 111', - zipCode: '21241111', - city: 'Qualquer Lugar', - state: 'QL', - country: 'BRA', - } + + const endDate = await cielo.recurrent + .modifyEndDate({ + paymentId: + firstRecurrency.payment.recurrentPayment.recurrentPaymentId, + endDate: '2021-01-09', + }) + .catch(error); + if (endDate) { + t.assert( + endDate.statusCode === 200, + 'StatusCode da modificação da recorrência terminar dia 09/01/2021 correto (200)' + ); + } + + const recurrencyDay = await cielo.recurrent + .modifyRecurrencyDay({ + paymentId: + firstRecurrency.payment.recurrentPayment.recurrentPaymentId, + recurrencyDay: 10, + }) + .catch(error); + if (recurrencyDay) { + t.assert( + recurrencyDay.statusCode === 200, + 'StatusCode da modificação da recorrência para dia 10 correto (200)' + ); + } + + const updateAmount: RecurrentModifyAmountModel = { + paymentId: firstRecurrency.payment.recurrentPayment.recurrentPaymentId, + amount: 156, // Valor do Pedido em centavos: 156 equivale a R$ 1,56 + }; + const amount = await cielo.recurrent + .modifyAmount(updateAmount) + .catch(error); + if (amount) { + t.assert( + amount.statusCode === 200, + 'StatusCode da modificação do valor para 156 correto (200)' + ); } - } - - const customer = await cielo.recurrent.modifyCustomer(updateCustomer).catch(error); - if (customer) { - t.assert(customer.statusCode === 200, 'StatusCode da modificação do Customer correto (200)') - } - - const endDate = await cielo.recurrent.modifyEndDate({ - paymentId: firstRecurrency.payment.recurrentPayment.recurrentPaymentId, - endDate: '2021-01-09' - }).catch(error) - if (endDate) { - t.assert(endDate.statusCode === 200, 'StatusCode da modificação da recorrência terminar dia 09/01/2021 correto (200)') - } - - const recurrencyDay = await cielo.recurrent.modifyRecurrencyDay({ - paymentId: firstRecurrency.payment.recurrentPayment.recurrentPaymentId, - recurrencyDay: 10 - }).catch(error) - if (recurrencyDay) { - t.assert(recurrencyDay.statusCode === 200, 'StatusCode da modificação da recorrência para dia 10 correto (200)') - } - - const updateAmount: RecurrentModifyAmountModel = { - paymentId: firstRecurrency.payment.recurrentPayment.recurrentPaymentId, - amount: 156 // Valor do Pedido em centavos: 156 equivale a R$ 1,56 - } - const amount = await cielo.recurrent.modifyAmount(updateAmount).catch(error) - if (amount) { - t.assert(amount.statusCode === 200, 'StatusCode da modificação do valor para 156 correto (200)') - } - - let newRecurrencyDate = new Date() - newRecurrencyDate.setDate(newRecurrencyDate.getDate() + 7) // Altera para a próxima semana - let nextRecurrency = `${newRecurrencyDate.getFullYear()}-${newRecurrencyDate.getMonth() + 1}-${newRecurrencyDate.getDate()}` - const updateNextPaymentDate: RecurrentModifyNextPaymentDateModel = { - paymentId: firstRecurrency.payment.recurrentPayment.recurrentPaymentId, - nextPaymentDate: nextRecurrency - } - const nextPaymentDate = await cielo.recurrent.modifyNextPaymentDate(updateNextPaymentDate).catch(error) - if (nextPaymentDate) { - t.assert(nextPaymentDate.statusCode === 200, 'StatusCode da modificação da data do próximo pagamento para 15/06/2016 correto (200)') - } - - const deactivateRecurrencyParams: RecurrentModifyModel = { - paymentId: firstRecurrency.payment.recurrentPayment.recurrentPaymentId - } - const deactivateRecurrency = await cielo.recurrent.deactivate(deactivateRecurrencyParams).catch(error) - if (deactivateRecurrency) { - t.assert(deactivateRecurrency.statusCode === 200, 'StatusCode da desativação da recorrência correto (200)') - } - - const recurrencyConsultingParams: ConsultTransactionRecurrentPaymentIdRequestModel = { - recurrentPaymentId: firstRecurrency.payment.recurrentPayment.recurrentPaymentId - } - const recurrencyConsulting = await cielo.consult.recurrent(recurrencyConsultingParams).catch(error) - if (recurrencyConsulting) { - t.assert(recurrencyConsulting.recurrentPayment.status === 3, 'Status da recorrência correto (3 - desativada pelo lojista)') - t.assert(recurrencyConsulting.recurrentPayment.interval === 'Monthly', 'Intervalo da recorrência correto (Monthly)') - t.assert(recurrencyConsulting.customer.email === 'customer@teste.com', 'Dados do cliente alterados com sucesso') - } - - t.end() - - -}); \ No newline at end of file + + let newRecurrencyDate = new Date(); + newRecurrencyDate.setDate(newRecurrencyDate.getDate() + 7); // Altera para a próxima semana + let nextRecurrency = `${newRecurrencyDate.getFullYear()}-${ + newRecurrencyDate.getMonth() + 1 + }-${newRecurrencyDate.getDate()}`; + const updateNextPaymentDate: RecurrentModifyNextPaymentDateModel = { + paymentId: firstRecurrency.payment.recurrentPayment.recurrentPaymentId, + nextPaymentDate: nextRecurrency, + }; + const nextPaymentDate = await cielo.recurrent + .modifyNextPaymentDate(updateNextPaymentDate) + .catch(error); + if (nextPaymentDate) { + t.assert( + nextPaymentDate.statusCode === 200, + 'StatusCode da modificação da data do próximo pagamento para 15/06/2016 correto (200)' + ); + } + + const deactivateRecurrencyParams: RecurrentModifyModel = { + paymentId: firstRecurrency.payment.recurrentPayment.recurrentPaymentId, + }; + const deactivateRecurrency = await cielo.recurrent + .deactivate(deactivateRecurrencyParams) + .catch(error); + if (deactivateRecurrency) { + t.assert( + deactivateRecurrency.statusCode === 200, + 'StatusCode da desativação da recorrência correto (200)' + ); + } + + const recurrencyConsultingParams: ConsultTransactionRecurrentPaymentIdRequestModel = { + recurrentPaymentId: + firstRecurrency.payment.recurrentPayment.recurrentPaymentId, + }; + const recurrencyConsulting = await cielo.consult + .recurrent(recurrencyConsultingParams) + .catch(error); + if (recurrencyConsulting) { + t.assert( + recurrencyConsulting.recurrentPayment.status === 3, + 'Status da recorrência correto (3 - desativada pelo lojista)' + ); + t.assert( + recurrencyConsulting.recurrentPayment.interval === 'Monthly', + 'Intervalo da recorrência correto (Monthly)' + ); + t.assert( + recurrencyConsulting.customer.email === 'customer@teste.com', + 'Dados do cliente alterados com sucesso' + ); + } + + const testeError: RecurrentCreateModel = { + merchantOrderId: '12345678', + customer: { + name: 'Fulano de Tal', + }, + payment: { + type: EnumCardType.CREDIT, + amount: 50, + installments: 1, + returnUrl: 'http://google.com.br', + recurrentPayment: { + authorizeNow: true, + endDate: '2020-12-12', + interval: EnumRecurrentPaymentInterval.MONTHLY, + }, + creditCard: { + cardNumber: '522aaa4049 1585 0591', + holder: 'Fulano de Tal', + expirationDate: '05/2022', + securityCode: '111', + saveCard: false, + brand: EnumBrands.MASTER, + }, + }, + }; + + // Testa uma recorrência com erro + const recurrencyError = await cielo.recurrent + .create(testeError) + .catch((error) => error); + + t.assert(recurrencyError.statusCode !== 200, 'Código do erro na transação correto'); + + t.end(); +});