paypal not returning to application after payment - java

In my current java/spring project, I am using the paypal-java-sdk to try implement a payment system to my application. A long time ago, I managed to make this work with a old project I've lost, with a code similar to what I have now, but now, when I run the application and try make a payment using the paypal sdk, I am redirect to the payment method selection page, and, either if I confirm or cancel the payment, I go to my account page instead of return to the application.
I have this code:
in my controller, this method receives the call from the view:
#RequestMapping(value = "/checkout", method=RequestMethod.GET)
public String checkout(#RequestParam("usuario_id") Integer usuario_id, #RequestParam(value="payerId", required=false) String payerId, #RequestParam(value="guid", required=false) String guid) throws com.paypal.base.rest.PayPalRESTException {
return "redirect:"+this.serv.checkout(usuario_id, payerId, guid);
}
in my service class, this 2 methods handles the payment using paypal:
public String checkout(Integer usuario_id, String payerId, String guid) throws com.paypal.base.rest.PayPalRESTException {
Usuario usuario = this.dao.findBy("id", usuario_id);
String clientId = paypalDao.get().getClientId();
String clientSecret = paypalDao.get().getClientSecret();
APIContext apiContext = new APIContext(clientId, clientSecret, "sandbox");
String redirectURL = "";
if(payerId != null) {
if(guid != null) {
Payment payment = new Payment();
payment.setId(map.get(guid));
PaymentExecution paymentExecution = new PaymentExecution();
paymentExecution.setPayerId(payerId);
payment.execute(apiContext, paymentExecution);
//saves the order data in the database and redirect to the order page
}
} else {
Payment createdPayment = createPayment(usuario, apiContext);
Iterator<Links> links = createdPayment.getLinks().iterator();
while (links.hasNext()) {
Links link = links.next();
if (link.getRel().equalsIgnoreCase("approval_url"))
redirectURL = link.getHref();
}
map.put(guid, createdPayment.getId());
}
return redirectURL;
}
public Payment createPayment(Usuario usuario, APIContext apiContext) throws com.paypal.base.rest.PayPalRESTException {
Amount amount = new Amount();
amount.setCurrency("BRL");
amount.setTotal(this.cart_total(usuario.getId()).toString());
String desc = "Lista de produtos comprados\n";
for(Produto produto : usuario.getCesta().getProdutos())
desc = desc + "* " + produto.getNome() + "\n";
Transaction transaction = new Transaction();
transaction.setAmount(amount);
transaction.setDescription(desc);
java.util.List<Transaction> transactions = new java.util.ArrayList<Transaction>();
transactions.add(transaction);
Payer payer = new Payer();
payer.setPaymentMethod("paypal");
Payment payment = new Payment();
payment.setIntent("sale");
payment.setPayer(payer);
payment.setTransactions(transactions);
RedirectUrls redirectUrls = new RedirectUrls();
redirectUrls.setCancelUrl(request.getContextPath() + "/cancel");
redirectUrls.setReturnUrl(request.getContextPath() + "/checkout?usuario_id="+usuario.getId()+"?guid="+UUID.randomUUID().toString());
payment.setRedirectUrls(redirectUrls);
return payment.create(apiContext);
}
anyone can give me a hint of what I am missing here?

Related

com.stripe.exception.InvalidRequestException: As per Indian regulations, export transactions require a customer name and address. in spring boot

i integrated stripe in my spring boot project
#PostMapping("/create-charge")
public #ResponseBody Response createCharge(String email, String token) {
if (token == null) {
return new Response(false, "Stripe payment token is missing. Please, try again later.");
}
String chargeId = stripeService.createCharge(email, token, 999); //$9.99 USD
if (chargeId == null) {
return new Response(false, "An error occurred while trying to create a charge.");
}
return new Response(true, "Success! Your charge id is " + chargeId);
}
My Service
public String createCharge(String email, String token, int amount) {
String id = null;
try {
Stripe.apiKey = API_SECRET_KEY;
Map<String, Object> chargeParams = new HashMap<>();
chargeParams.put("amount", amount);
chargeParams.put("currency", "usd");
chargeParams.put("description", "Charge for " + email);
chargeParams.put("source", token); // ^ obtained with Stripe.js
//create a charge
Charge charge = Charge.create(chargeParams);
id = charge.getId();
} catch (Exception ex) {
ex.printStackTrace();
}
return id;
}
i am getting exception
com.stripe.exception.InvalidRequestException: As per Indian regulations, export transactions require a customer name and address. More info here: https://stripe.com/docs/india-exports
How should i pass the address in request?
I tried to pass the address like this
Stripe.apiKey = API_SECRET_KEY;
Map<String, Object> chargeParams = new HashMap<>();
chargeParams.put("amount", amount);
chargeParams.put("currency", "usd");
chargeParams.put("description", "Charge for " + email);
chargeParams.put("source", token); // ^ obtained with Stripe.js
Map<String, Object> customerParams = new HashMap<>();
Map<String, String> addressParams = new HashMap<>();
customerParams.put("description", "Customer for " + email);
customerParams.put("email", email);
customerParams.put("address", addressParams);
addressParams.put("city", "varanasi");
addressParams.put("country", "india");
customerParams.put("source", token); // ^ obtained with Stripe.js
//create a new customer
Customer customer = Customer.create(customerParams);
chargeParams.put("customer", customer.getId());
//create a charge
Charge charge = Charge.create(chargeParams);
id = charge.getId();
but now getting exception
com.stripe.exception.InvalidRequestException: Customer cus_JIMd90oUI9V8e6 does not have a linked source with ID tok_1Iflu8AuNrJFnosEZI2huyYo.; code: missing
when i changed the currency to inr the issue is fixed but i dont want to change the currency
I received this exception as well while creating charge using Stripe API.
I'm not much familiar with Java but assuming that there's no other error.
Try this: change the currency from USD to INR.
This worked for me, so hopefully will work for you as well.

How do I access 'me/accounts' access tokens through java using restfb?

I'm trying to access the details of the Facebook pages I'm an admin on through restfb. I can get my user details but when I try to get the details from 'me/accounts' it just returns null.
I've tried using different types and classes but still won't show what I need. However it works fine using the Facebook Graph API tool
private void authUser(ActionEvent event) {
String appId = "(My App ID)";
String domain = "https://www.google.com";
String authUrl = "https://graph.facebook.com/oauth/authorize?type=user_agent&client_id="+appId+"&redirect_uri="+domain+"&scope=ads_management, ads_read, business_management, email, groups_access_member_info, leads_retrieval, manage_pages, pages_manage_cta, pages_manage_instant_articles, pages_messaging, pages_messaging_phone_number, pages_messaging_subscriptions, pages_show_list, publish_pages, publish_to_groups, publish_video, read_audience_network_insights, read_insights, read_page_mailboxes, user_age_range, user_birthday, user_events, user_friends, user_gender, user_hometown, user_likes, user_link, user_location, user_photos, user_posts, user_status, user_tagged_places, user_videos";
System.setProperty("webdriver.chrome.driver", "chromedriver");
WebDriver driver = new ChromeDriver();
driver.get(authUrl);
String accessToken;
String accessToken2 = null;
while(true){
if(!driver.getCurrentUrl().contains("facebook")){
String url = driver.getCurrentUrl();
accessToken = url.replaceAll(".*#access_token=(.+)&.*","$1");
int indexOfLast = accessToken.lastIndexOf("&");
if(indexOfLast >=0) accessToken2 = accessToken.substring(0, indexOfLast);
System.out.println(accessToken);
System.out.println(accessToken2);
driver.quit();
driver = null;
FacebookClient fbClient = new DefaultFacebookClient(accessToken2, com.restfb.Version.VERSION_3_2);
User user = fbClient.fetchObject("me", User.class, Parameter.with("fields", "name, email"));
User account = fbClient.fetchObject("me/accounts", User.class, Parameter.with("fields", "name"));
name.setText(user.getName());
id.setText(user.getId());
if (user.getEmail() == null) {
email.setText("Unable to show email");
} else {
email.setText(user.getEmail());
}
if (account.getName()== null) {
System.out.println("Null");
} else {
System.out.println(account.getName());
}
}
}
}

Manage Simultaneous calls to a REST Service without Duplicate an ID in JAVA

I´m build a REST service through Spring and Swagger with CMIS Protocol in Maven. My services works well until the moment when I´m doing simultaneous calls through Jmeter to stress the system. Context: the service get an ID from an ID creator to generate a node in Alfresco. The id cannot be repeated in the system. this id creator take the last created node and sum +1. I tried with Thread.sleep and TimeUnit. The Jmeter Answer in 10 calls in one sec that the Node was created 10 times with the same ID.
Extract of current code: Controller:
#ApiOperation(value = "Crea un Tipo de documento")
#RequestMapping(value = "/create2", method = RequestMethod.POST)
ResponseMessage createTypeDocument2(#RequestParam String description) throws InterruptedException {
return typeDocumentService.createTypeDocument(description);
}
Service:
#Transactional
public ResponseMessage createTypeDocument(String description) throws InterruptedException {
Session session = obtieneSesion();
int id = this.idCreator2();
int aux = 0;
if(searchDocuments(id)==null) {
aux=0;
}else {
aux = Integer.parseInt(searchDocuments(id).getProperty("bc:id").getValueAsString());
}
ResponseMessage rm = new ResponseMessage();
TimeUnit.MILLISECONDS.sleep(new Random().nextInt(500));
Thread.sleep(1000);
if(id != aux ) {
SimpleDateFormat sdf = new SimpleDateFormat("SSS");
Date date = new Date();
String nombre = sdf.format(date.getTime());
DocumentTypeDTO docFilter = new DocumentTypeDTO();
Folder root = (Folder) session.getObjectByPath("/DataList-BCH");
HashMap<String, Object> metadata = new HashMap<String, Object>();
metadata.put(PropertyIds.OBJECT_TYPE_ID, "***************");
metadata.put(PropertyIds.NAME, nombre);
metadata.put("bc:id", id);
metadata.put("bc:available", activo);
metadata.put("bc:description", description);
Document newDoc = root.createDocument(metadata, null, null);
docFilter.setId( Integer.parseInt(newDoc.getProperty("bc:id").getValueAsString()));
docFilter.setDescription(newDoc.getProperty("bc:description").getValueAsString());
docFilter.setUuid(newDoc.getId().replaceAll(";1.0", "").replace("workspace://SpacesStore/", ""));
rm.setMensaje("Exitoso");
rm.setCodigo(200);
rm.setObjeto(docFilter);
return rm;
}else {
rm.setCodigo(-1);
rm.setMensaje("La ID ya existe");
return rm;
}
}
SearchDocument method if the object is not found return null. I try multiple options without results, for that reason I need your help to resolve it. Thanks in Advice
RESOLVED IN STACKOVERFLOW IN SPANISH:
RESOLVED

How to get user credentials from request?

I am working on Restlet tutorial example concerning coarse-grained authorization:
public class MyApiWithRoleAuthorization extends Application {
//Define role names
public static final String ROLE_USER = "user";
public static final String ROLE_OWNER = "owner";
#Override
public Restlet createInboundRoot() {
//Create the authenticator, the authorizer and the router that will be protected
ChallengeAuthenticator authenticator = createAuthenticator();
RoleAuthorizer authorizer = createRoleAuthorizer();
Router router = createRouter();
Router baseRouter = new Router(getContext());
//Protect the resource by enforcing authentication then authorization
authorizer.setNext(Resource0.class);
authenticator.setNext(baseRouter);
//Protect only the private resources with authorizer
//You could use several different authorizers to authorize different roles
baseRouter.attach("/resourceTypePrivate", authorizer);
baseRouter.attach("/resourceTypePublic", router);
return authenticator;
}
private ChallengeAuthenticator createAuthenticator() {
ChallengeAuthenticator guard = new ChallengeAuthenticator(
getContext(), ChallengeScheme.HTTP_BASIC, "realm");
//Create in-memory users with roles
MemoryRealm realm = new MemoryRealm();
User user = new User("user", "user");
realm.getUsers().add(user);
realm.map(user, Role.get(this, ROLE_USER));
User owner = new User("owner", "owner");
realm.getUsers().add(owner);
realm.map(owner, Role.get(this, ROLE_OWNER));
//Attach verifier to check authentication and enroler to determine roles
guard.setVerifier(realm.getVerifier());
guard.setEnroler(realm.getEnroler());
return guard;
}
private RoleAuthorizer createRoleAuthorizer() {
//Authorize owners and forbid users on roleAuth's children
RoleAuthorizer roleAuth = new RoleAuthorizer();
roleAuth.getAuthorizedRoles().add(Role.get(this, ROLE_OWNER));
roleAuth.getForbiddenRoles().add(Role.get(this, ROLE_USER));
return roleAuth;
}
private Router createRouter() {
//Attach Server Resources to given URL
Router router = new Router(getContext());
router.attach("/resource1/", Resource1.class);
router.attach("/resource2/", Resource2.class);
return router;
}
public static void main(String[] args) throws Exception {
//Attach application to http://localhost:9000/v1
Component c = new Component();
c.getServers().add(Protocol.HTTP, 9000);
c.getDefaultHost().attach("/v1", new MyApiWithRoleAuthorization());
c.start();
}
}
I create a class for checking user credentials:
public class Resource1 extends ServerResource{
#Get
public String represent() throws Exception {
User user = getRequest().getClientInfo().getUser();
String identifier = user.getIdentifier();
char[] pass = user.getSecret();
return this.getClass().getSimpleName() + " found ! User: " + identifier +
"; password = " + charArrayToString(pass) ;
}
private String charArrayToString(char[] chars ) {
String result = "";
for (char c : chars){
result += c;
}
return result;
}
}
When I go to resource http://localhost:9000/v1/resourceTypePublic/resource1/ the application asks for credentials and I input "user", "user" (or "owner", "owner"). But I get internal server error. The reason is that variable pass in return statement
return this.getClass().getSimpleName() + " found ! User: " + identifier +
"; password = " + charArrayToString(pass) ;
has null value. The statement without this variable works ok:
return this.getClass().getSimpleName() + " found ! User: " + identifier;
and returns user login. But what about the secret? Why it returns null value despite the user secret had been inputted?
User object created with statement
User user = getRequest().getClientInfo().getUser();
does not contain information about password despite it has a field secret. There is another way to get user credentials:
char[] pass = getChallengeResponse().getSecret();

Spring MVC, attempting to edit but creating new objects

I have an MVC app that is creating new offices instead of updating them on when using an edit form. Please help me understand why this is happening.
Search method that populates the search results:
#RequestMapping(value = "/searchResults", method = RequestMethod.POST)
public ModelAndView search(#RequestParam String searchCriteria, HttpServletRequest request) {
List<Office> offices = officeServiceImpl.search(searchCriteria);
return new ModelAndView("searchResults", "offices", offices);
}
Here's what the link to the edit form looks like on the search results page:
Edit Office
Here is the Controller's edit GET method that populates the form with the existing Office:
#RequestMapping(value = "/{officeId}/edit", method = RequestMethod.GET)
#Transactional(noRollbackFor=NoResultException.class)
public ModelAndView initUpdateOfficeForm(
#PathVariable("officeId") Long officeId, Model model) {
Office office = officeServiceImpl.find(officeId);
//prepareEditFormModelAndView(office) just converts some objects to strings for typeahead form population
return prepareEditFormModelAndView(office);
}
Here is the edit POST method:
#RequestMapping(value = "/{officeId}/edit", method = RequestMethod.POST)
public ModelAndView processUpdateOfficeForm(#ModelAttribute("office") #Valid Office office,
BindingResult result, SessionStatus status) {
if (! "united states of america".equals(office.getFolderStrings().toLowerCase())) {
//This portion of code converts the typeahead strings to objects
result = tryCountries(office, result);
result = tryDepartments(office, result);
result = tryEmployees(office, result);
}
if (result.hasErrors()) {
return prepareEditFormModelAndView(office);
} else {
officeServiceImpl.save(office);
status.setComplete();
return new ModelAndView("editResult", "office", office);
}
}
officeServiceImpl calls officeRepositoryImpl method save which looks like:
#Override
public Office save(Office office) {
em.merge(office);
em.flush();
return office;
}
Thanks
Edit: Adding prepareEditFormModelAndView(office), This method attempts to build strings from associated objects:
#Transactional(noRollbackFor={NoResultException.class, IndexOutOfBoundsException.class})
private ModelAndView prepareEditFormModelAndView(Office office) {
String departmentStrings = "";
String employeeStrings = "";
List<OOM> officeOOMs = new ArrayList<OOM>();
StringBuilder sb = new StringBuilder();
try {
officeOOMs = oomServiceImpl.getOOMsForCurrentOffice(office.getId());
} catch (NoResultException e) {
officeOOMs = null;
}
for (OOM o : officeOOMs) {
try {
Employee tempEmployee = employeeServiceImpl.find(o
.getEmployeeId());
sb.append(tempEmployee.getDisplayName() + ", ");
} catch (NoResultException e) {
sb.append("Not found in system");
}
}
employeeStrings = sb.toString();
if ((! "".equals(office.getDepartmentStringsOnForm())) && office.getDepartmentStringsOnForm() != null) {
departmentStrings = office.getDepartmentStringsOnForm();
}
String folderStrings = "";
try {
folderStrings = kmlFolderServiceImpl.getInternationalOfficeString(office.getId());
LOGGER.info("Folder Strings: " + folderStrings);
} catch (NoResultException e) {
folderStrings = "";
LOGGER.info("Folder Strings: " + "no result");
}
boolean isInternational = office.isInternational();
ModelAndView result = new ModelAndView("editOfficeForm", "office", office);
result.addObject("departmentStrings", departmentStrings);
result.addObject("isInternational", isInternational);
result.addObject("folderStrings", folderStrings);
result.addObject("employeeStrings", employeeStrings);
return result;
}
I am adding a previous comment here, for better clarification. According to the OP the following fixes the problem:
When the ID is not in the form then when the model is posted back no ID is set to the entity making the persistence provider believe it is new entity.
Therefor the most obvious solution is to post the ID of the entity as well in the save operation (probably using a hidden field).
Another solution would be to try to load the entity in the database based on some business key
to see if the entity is new or not.

Categories