Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: secure fields events #5

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<dependency>
<groupId>com.mercadopago</groupId>
<artifactId>sdk-java</artifactId>
<version>1.11.0</version>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.mercadopago.sample.controller;

import com.mercadopago.sample.dto.PaymentResponseDTO;
import com.mercadopago.sample.dto.CardPaymentDTO;
import com.mercadopago.sample.dto.PaymentResponseDTO;
import com.mercadopago.sample.service.CardPaymentService;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand All @@ -11,12 +12,10 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@RestController
@RequestMapping("/process_payment")
public class CardPaymentController {
private CardPaymentService cardPaymentService;
private final CardPaymentService cardPaymentService;

@Autowired
public CardPaymentController(CardPaymentService cardPaymentService) {
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/com/mercadopago/sample/dto/CardPaymentDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.annotation.JsonProperty;

import java.math.BigDecimal;
import javax.validation.constraints.NotNull;

public class CardPaymentDTO {
Expand All @@ -14,7 +15,7 @@ public class CardPaymentDTO {
private String paymentMethodId;

@NotNull
private Float transactionAmount;
private BigDecimal transactionAmount;

@NotNull
private Integer installments;
Expand Down Expand Up @@ -53,11 +54,11 @@ public void setPaymentMethodId(String paymentMethodId) {
this.paymentMethodId = paymentMethodId;
}

public Float getTransactionAmount() {
public BigDecimal getTransactionAmount() {
return transactionAmount;
}

public void setTransactionAmount(Float transactionAmount) {
public void setTransactionAmount(BigDecimal transactionAmount) {
this.transactionAmount = transactionAmount;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
package com.mercadopago.sample.dto;

public class PaymentResponseDTO {
private String id;
private Long id;
private String status;
private String detail;

public PaymentResponseDTO(String id, String status, String detail) {
public PaymentResponseDTO(Long id, String status, String detail) {
this.id = id;
this.status = status;
this.detail = detail;
}

public String getId() {
public Long getId() {
return id;
}

public void setId(String id) {
public void setId(Long id) {
this.id = id;
}

Expand Down
107 changes: 49 additions & 58 deletions src/main/java/com/mercadopago/sample/service/CardPaymentService.java
Original file line number Diff line number Diff line change
@@ -1,69 +1,60 @@
package com.mercadopago.sample.service;

import com.mercadopago.MercadoPagoConfig;
import com.mercadopago.client.common.IdentificationRequest;
import com.mercadopago.client.payment.PaymentClient;
import com.mercadopago.client.payment.PaymentCreateRequest;
import com.mercadopago.client.payment.PaymentPayerRequest;
import com.mercadopago.exceptions.MPApiException;
import com.mercadopago.exceptions.MPException;
import com.mercadopago.resources.payment.Payment;
import com.mercadopago.sample.dto.CardPaymentDTO;
import com.mercadopago.sample.dto.PaymentResponseDTO;
import com.mercadopago.sample.exception.MercadoPagoException;
import com.mercadopago.sample.dto.CardPaymentDTO;
import com.mercadopago.MercadoPago;
import com.mercadopago.exceptions.MPException;
import com.mercadopago.resources.Payment;
import com.mercadopago.resources.datastructures.payment.Identification;
import com.mercadopago.resources.datastructures.payment.Payer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class CardPaymentService {
@Value("${mercado_pago_sample_access_token}")
private String mercadoPagoAccessToken;

public PaymentResponseDTO processPayment(CardPaymentDTO cardPaymentDTO) {
try {
MercadoPago.SDK.setAccessToken(mercadoPagoAccessToken);

Payment payment = new Payment();
payment.setTransactionAmount(cardPaymentDTO.getTransactionAmount())
.setToken(cardPaymentDTO.getToken())
.setDescription(cardPaymentDTO.getProductDescription())
.setInstallments(cardPaymentDTO.getInstallments())
.setPaymentMethodId(cardPaymentDTO.getPaymentMethodId());

Identification identification = new Identification();
identification.setType(cardPaymentDTO.getPayer().getIdentification().getType())
.setNumber(cardPaymentDTO.getPayer().getIdentification().getNumber());

Payer payer = new Payer();
payer.setEmail(cardPaymentDTO.getPayer().getEmail());
payer.setIdentification(identification);

payment.setPayer(payer);

Payment createdPayment = payment.save();

this.validatePaymentResult(createdPayment);

PaymentResponseDTO paymentResponseDTO = new PaymentResponseDTO(
createdPayment.getId(),
String.valueOf(createdPayment.getStatus()),
createdPayment.getStatusDetail()
);

return paymentResponseDTO;
} catch (MPException exception) {
System.out.println(exception.getMessage());
throw new MercadoPagoException(exception.getMessage());
}
}

private void validatePaymentResult(Payment createdPayment) throws MPException {
if(createdPayment.getId() == null) {
String errorMessage = "Unknown error cause";

if(createdPayment.getLastApiResponse() != null) {
String sdkErrorMessage = createdPayment.getLastApiResponse().getJsonElementResponse().getAsJsonObject().get("message").getAsString();
errorMessage = sdkErrorMessage != null ? sdkErrorMessage : errorMessage;
}

throw new MPException(errorMessage);
}
@Value("${mercado_pago_sample_access_token}")
private String mercadoPagoAccessToken;

public PaymentResponseDTO processPayment(CardPaymentDTO cardPaymentDTO) {
try {
MercadoPagoConfig.setAccessToken(mercadoPagoAccessToken);

PaymentClient paymentClient = new PaymentClient();

PaymentCreateRequest paymentCreateRequest =
PaymentCreateRequest.builder()
.transactionAmount(cardPaymentDTO.getTransactionAmount())
.token(cardPaymentDTO.getToken())
.description(cardPaymentDTO.getProductDescription())
.installments(cardPaymentDTO.getInstallments())
.paymentMethodId(cardPaymentDTO.getPaymentMethodId())
.payer(
PaymentPayerRequest.builder()
.email(cardPaymentDTO.getPayer().getEmail())
.identification(
IdentificationRequest.builder()
.type(cardPaymentDTO.getPayer().getIdentification().getType())
.number(cardPaymentDTO.getPayer().getIdentification().getNumber())
.build())
.build())
.build();

Payment createdPayment = paymentClient.create(paymentCreateRequest);

return new PaymentResponseDTO(
createdPayment.getId(),
String.valueOf(createdPayment.getStatus()),
createdPayment.getStatusDetail());
} catch (MPApiException apiException) {
System.out.println(apiException.getApiResponse().getContent());
throw new MercadoPagoException(apiException.getApiResponse().getContent());
} catch (MPException exception) {
System.out.println(exception.getMessage());
throw new MercadoPagoException(exception.getMessage());
}
}
}
8 changes: 8 additions & 0 deletions src/main/resources/static/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -405,4 +405,12 @@ footer p a:hover {

#fail-response, #success-response {
display: none;
}

.validation-error {
border-color: red;
}

#validation-error-messages p {
color: red;
}
134 changes: 87 additions & 47 deletions src/main/resources/static/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,61 @@ const mercadopago = new MercadoPago(publicKey);
function loadCardForm() {
const productCost = document.getElementById('amount').value;
const productDescription = document.getElementById('product-description').innerText;
const payButton = document.getElementById("form-checkout__submit");
const validationErrorMessages= document.getElementById('validation-error-messages');

const cardForm = mercadopago.cardForm({
amount: productCost,
iframe: true,
form: {
id: "form-checkout",
cardholderName: {
id: "form-checkout__cardholderName",
placeholder: "Holder name",
},
cardholderEmail: {
id: "form-checkout__cardholderEmail",
placeholder: "E-mail",
},
cardNumber: {
id: "form-checkout__cardNumber",
placeholder: "Card number",
style: {
fontSize: "1rem"
},
},
cardExpirationDate: {
id: "form-checkout__cardExpirationDate",
placeholder: "MM/YYYY",
style: {
fontSize: "1rem"
},
},
securityCode: {
id: "form-checkout__securityCode",
placeholder: "Security code",
style: {
fontSize: "1rem"
},
},
installments: {
id: "form-checkout__installments",
placeholder: "Installments",
},
identificationType: {
id: "form-checkout__identificationType",
const form = {
id: "form-checkout",
cardholderName: {
id: "form-checkout__cardholderName",
placeholder: "Holder name",
},
cardholderEmail: {
id: "form-checkout__cardholderEmail",
placeholder: "E-mail",
},
cardNumber: {
id: "form-checkout__cardNumber",
placeholder: "Card number",
style: {
fontSize: "1rem"
},
identificationNumber: {
id: "form-checkout__identificationNumber",
placeholder: "Identification number",
},
expirationDate: {
id: "form-checkout__expirationDate",
placeholder: "MM/YYYY",
style: {
fontSize: "1rem"
},
issuer: {
id: "form-checkout__issuer",
placeholder: "Issuer",
},
securityCode: {
id: "form-checkout__securityCode",
placeholder: "Security code",
style: {
fontSize: "1rem"
},
},
installments: {
id: "form-checkout__installments",
placeholder: "Installments",
},
identificationType: {
id: "form-checkout__identificationType",
},
identificationNumber: {
id: "form-checkout__identificationNumber",
placeholder: "Identification number",
},
issuer: {
id: "form-checkout__issuer",
placeholder: "Issuer",
},
};

const cardForm = mercadopago.cardForm({
amount: productCost,
iframe: true,
form,
callbacks: {
onFormMounted: error => {
if (error)
Expand Down Expand Up @@ -120,7 +124,6 @@ function loadCardForm() {
},
onFetching: (resource) => {
console.log("Fetching resource: ", resource);
const payButton = document.getElementById("form-checkout__submit");
payButton.setAttribute('disabled', true);
return () => {
payButton.removeAttribute("disabled");
Expand All @@ -134,11 +137,48 @@ function loadCardForm() {
}

return token;
},
onValidityChange: (error, field) => {
const input = document.getElementById(form[field].id);
removeFieldErrorMessages(input, validationErrorMessages);
addFieldErrorMessages(input, validationErrorMessages, error);
enableOrDisablePayButton(validationErrorMessages, payButton);
}
},
});
};

function removeFieldErrorMessages(input, validationErrorMessages) {
Array.from(validationErrorMessages.children).forEach(child => {
const shouldRemoveChild = child.id.includes(input.id);
if (shouldRemoveChild) {
validationErrorMessages.removeChild(child);
}
});
}

function addFieldErrorMessages(input, validationErrorMessages, error) {
if (error) {
input.classList.add('validation-error');
error.forEach((e, index) => {
const p = document.createElement('p');
p.id = `${input.id}-${index}`;
p.innerText = e.message;
validationErrorMessages.appendChild(p);
});
} else {
input.classList.remove('validation-error');
}
}

function enableOrDisablePayButton(validationErrorMessages, payButton) {
if (validationErrorMessages.children.length > 0) {
payButton.setAttribute('disabled', true);
} else {
payButton.removeAttribute('disabled');
}
}

// Handle transitions
document.getElementById('checkout-btn').addEventListener('click', function(){
$('.container__cart').fadeOut(500);
Expand Down
Loading