Version number: 2.2.0-SNAPSHOT
And the HeatClinic: DemoApplication
I followed the instruction on the Quick Start but ran into some issues then went to the advanced setup, to no avail. I kept getting this error:
Code: Select all
Problem accessing /checkout/complete. Reason:
Unable to checkout order -- id: 1
Caused by:
org.broadleafcommerce.core.checkout.service.exception.CheckoutException: Unable to checkout order -- id: 1
at org.broadleafcommerce.core.checkout.service.CheckoutServiceImpl.performCheckout(CheckoutServiceImpl.java:88)
at org.broadleafcommerce.core.web.controller.checkout.BroadleafCheckoutController.completeSecureCreditCardCheckout(BroadleafCheckoutController.java:401)
at org.sakotek.controller.checkout.CheckoutController.completeSecureCreditCardCheckout(CheckoutController.java:127)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:100)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:604)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:565)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:643)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1331)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.broadleafcommerce.cms.web.URLHandlerFilter.doFilterInternal(URLHandlerFilter.java:74)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:166)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1302)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.broadleafcommerce.profile.web.core.security.SessionFixationProtectionFilter.doFilter(SessionFixationProtectionFilter.java:90)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.broadleafcommerce.core.web.order.security.CartStateFilter.doFilter(CartStateFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.broadleafcommerce.profile.web.core.security.CustomerStateFilter.doFilter(CustomerStateFilter.java:147)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.broadleafcommerce.common.security.handler.CsrfFilter.doFilter(CsrfFilter.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.channel.ChannelProcessingFilter.doFilter(ChannelProcessingFilter.java:144)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:166)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1302)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.broadleafcommerce.common.web.BroadleafRequestFilter.doFilterInternal(BroadleafRequestFilter.java:152)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:147)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1302)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:448)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:131)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
at org.eclipse.jetty.server.handler.ContextHandler.__doHandle(ContextHandler.java:1067)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:377)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:192)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1001)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111)
at org.eclipse.jetty.server.Server.handle(Server.java:360)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454)
at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:900)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:954)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:851)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77)
at org.eclipse.jetty.io.nio.SslConnection.handle(SslConnection.java:191)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:622)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:46)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:603)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:538)
at java.lang.Thread.run(Thread.java:680)
Caused by: org.broadleafcommerce.core.payment.service.exception.PaymentException: Unable to execute payment for order -- id: 1
at org.broadleafcommerce.core.payment.service.CompositePaymentServiceImpl.executePayment(CompositePaymentServiceImpl.java:69)
at org.broadleafcommerce.core.checkout.service.workflow.PaymentServiceActivity.execute(PaymentServiceActivity.java:46)
at org.broadleafcommerce.core.workflow.SequenceProcessor.doActivities(SequenceProcessor.java:62)
at org.broadleafcommerce.core.checkout.service.CheckoutServiceImpl.performCheckout(CheckoutServiceImpl.java:75)
... 100 more
Caused by: org.broadleafcommerce.core.workflow.WorkflowException: org.broadleafcommerce.core.workflow.WorkflowException: java.lang.IllegalArgumentException: Must set the Request Parameter Map on the PaymentInfo instance.
at org.broadleafcommerce.core.workflow.DefaultErrorHandler.handleError(DefaultErrorHandler.java:45)
at org.broadleafcommerce.core.workflow.SequenceProcessor.doActivities(SequenceProcessor.java:67)
at org.broadleafcommerce.core.payment.service.CompositePaymentServiceImpl.executePayment(CompositePaymentServiceImpl.java:55)
... 103 more
Caused by: org.broadleafcommerce.core.workflow.WorkflowException: java.lang.IllegalArgumentException: Must set the Request Parameter Map on the PaymentInfo instance.
at org.broadleafcommerce.core.workflow.DefaultErrorHandler.handleError(DefaultErrorHandler.java:45)
at org.broadleafcommerce.core.workflow.SequenceProcessor.doActivities(SequenceProcessor.java:67)
at org.broadleafcommerce.core.payment.service.workflow.CompositeActivity.execute(CompositeActivity.java:35)
at org.broadleafcommerce.core.workflow.SequenceProcessor.doActivities(SequenceProcessor.java:62)
... 104 more
Caused by: java.lang.IllegalArgumentException: Must set the Request Parameter Map on the PaymentInfo instance.
at org.springframework.util.Assert.isTrue(Assert.java:65)
at org.broadleafcommerce.payment.service.module.AuthorizeNetPaymentModule.authorizeAndDebit(AuthorizeNetPaymentModule.java:94)
at org.broadleafcommerce.core.payment.service.PaymentServiceImpl.authorizeAndDebit(PaymentServiceImpl.java:74)
at org.broadleafcommerce.core.payment.service.workflow.PaymentActivity.execute(PaymentActivity.java:67)
at org.broadleafcommerce.core.workflow.SequenceProcessor.doActivities(SequenceProcessor.java:62)
... 106 more
I have setup my authorize.net account and have been using that for a while now. May be I should say I have not even gotten to the point where the application is posted to the gateway.
Here is my local.properties:
Code: Select all
authorizenet.api.login.id=adfeaesgsdg [this value has been removed]
authorizenet.transaction.key=sfagdgdggd [this value has been removed]
authorizenet.merchant.md5.key=md5 hash I entered
authorizenet.relay.response.url=http://localhost:8080/checkout/process
authorizenet.confirm.url=http://localhost:8080/checkout/confirmation
authorizenet.error.url=http://localhost:8080/commerce/authorizenet/error
authorizenet.server.url=https://test.authorize.net/gateway/transact.dll
authorizenet.x_test_request=FALSE
and my applicationContext.xml
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<bean id="blCreditCardService" class="org.broadleafcommerce.core.payment.service.PaymentServiceImpl">
<property name="paymentModule" ref="blAuthorizeNetModule" />
</bean>
<bean id="blAuthorizeNetModule" class="org.broadleafcommerce.payment.service.module.AuthorizeNetPaymentModule">
<property name="authorizeNetPaymentService" ref="blAuthorizeNetVendorOrientedPaymentService" />
<property name="stateService" ref="blStateService" />
<property name="countryService" ref="blCountryService" />
<property name="customerService" ref="blCustomerService" />
</bean>
<bean id="blAuthorizeNetVendorOrientedPaymentService" class="org.broadleafcommerce.vendor.authorizenet.service.payment.AuthorizeNetPaymentServiceImpl">
<property name="failureReportingThreshold" value="1" />
<property name="gatewayRequest">
<bean class="org.broadleafcommerce.vendor.authorizenet.service.payment.AuthorizeNetGatewayRequestImpl">
<property name="apiLoginId" value="${authorizenet.api.login.id}" />
<property name="transactionKey" value="${authorizenet.transaction.key}" />
<property name="relayResponseUrl" value="${authorizenet.relay.response.url}" />
<property name="merchantMD5Key" value="${authorizenet.merchant.md5.key}" />
</bean>
</property>
</bean>
<bean id="blConfiguration" class="org.broadleafcommerce.common.config.RuntimeEnvironmentPropertiesConfigurer" />
<bean id="blMergedDataSources" class="org.springframework.beans.factory.config.MapFactoryBean">
<property name="sourceMap">
<map>
<entry key="jdbc/web" value-ref="webDS" />
<entry key="jdbc/webSecure" value-ref="webSecureDS" />
<entry key="jdbc/cmsStorage" value-ref="webStorageDS" />
</map>
</property>
</bean>
<bean id="blMergedPersistenceXmlLocations" class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
<value>classpath*:/META-INF/persistence.xml</value>
</list>
</property>
</bean>
<!-- Set up Broadleaf messaging -->
<bean id="resourceBundleExtensionPoint" class="org.broadleafcommerce.common.util.ResourceBundleExtensionPoint" />
<bean id="messageSource" class="org.broadleafcommerce.common.util.BLResourceBundleMessageSource">
<constructor-arg>
<list>
<value>messages</value>
</list>
</constructor-arg>
<constructor-arg ref="resourceBundleExtensionPoint" />
</bean>
<!-- Set up custom entity overrides. These are defined in core/src/main/resources -->
<bean id="blMergedEntityContexts" class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
<value>classpath:applicationContext-entity.xml</value>
</list>
</property>
</bean>
<!-- Delete this bean to enable caching - leaving it on for development
is recommended -->
<!-- as it will allow changes made in the admin or directly on the database
to be reflected -->
<!-- immediately. However, caching is obviously beneficial in production. -->
<bean id="blMergedCacheConfigLocations"
class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
<value>classpath:bl-override-ehcache.xml</value>
</list>
</property>
</bean>
<!-- Delete this section to disable the embedded solr search service. Although
this will result in a smaller -->
<!-- application footprint, it will default the search service to use the
database implementation, which -->
<!-- is slower and less full-featured. Broadleaf suggests maintaining this
solr implementation in the vast -->
<!-- majority of cases. Note that you may also pass in a bean reference
to a SolrServer if you would prefer -->
<!-- to use a standalone solr server. (The default constructor will create
an embedded one at solrHome) -->
<bean id="solrEmbedded" class="java.lang.String">
<constructor-arg value="solrhome" />
</bean>
<bean id="blSearchService" class="org.broadleafcommerce.core.search.service.solr.SolrSearchServiceImpl">
<constructor-arg name="solrServer" ref="${solr.source}" />
</bean>
<bean id="rebuildIndexJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="blSearchService" />
<property name="targetMethod" value="rebuildIndex" />
</bean>
<bean id="rebuildIndexTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="rebuildIndexJobDetail" />
<property name="startDelay" value="${solr.index.start.delay}" />
<property name="repeatInterval" value="${solr.index.repeat.interval}" />
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="rebuildIndexTrigger" />
</list>
</property>
</bean>
<!-- This is an example of a custom dialect definition that uses a custom
processor -->
<!-- The second bean registers the dialct to the blWebTemplateEngine -->
<!-- Note that the same thing could be done for the blEmailTemplateEngine -->
<!-- <bean id="myDialect" class="org.sakotek.common.web.dialect.MyDialect">
<property name="processors"> <set> <bean class="org.sakotek.common.web.processor.MyProcessor"
/> </set> </property> </bean> <bean id="blWebTemplateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
<property name="dialects"> <set> <ref bean="myDialect" /> </set> </property>
</bean> -->
<!-- The following two beans are defined like this in Broadleaf Commerce.
However, -->
<!-- you may want to override the bean definitions by uncommenting these
two beans -->
<!-- to control whether or not templates are cacheable. This will generally
be desireable -->
<!-- in production environments, but likely not in development environments. -->
<!-- <bean id="blWebTemplateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/" /> <property name="suffix"
value=".html" /> <property name="templateMode" value="HTML5" /> <property
name="cacheable" value="false"/> <property name="characterEncoding" value="UTF-8"
/> </bean> <bean id="blEmailTemplateResolver" class="org.thymeleaf.templateresolver.ClassLoaderTemplateResolver">
<property name="prefix" value="emailTemplates/" /> <property name="suffix"
value=".html" /> <property name="templateMode" value="HTML5" /> <property
name="cacheable" value="false"/> <property name="characterEncoding" value="UTF-8"
/> </bean> -->
</beans>
I changed the checkout controller to extend BroadleafAuthorizeNetController instead of BraodleafCheckoutController as shown bellow and also added this piece os code:
Code: Select all
@RequestMapping(value = "/process", method = RequestMethod.POST, produces = "text/html")
public @ResponseBody String processAuthorizeNetAuthorizeAndDebit(HttpServletRequest request, HttpServletResponse response, Model model, @ModelAttribute("shippingInfoForm") ShippingInfoForm shippingForm, @ModelAttribute("billingInfoForm") BillingInfoForm billingForm) throws NoSuchAlgorithmException, UnsupportedEncodingException, PricingException, InvalidKeyException {
return super.processAuthorizeNetAuthorizeAndDebit(request, response, model);
}
Code: Select all
/*
* Copyright 2008-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sakotek.controller.checkout;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.collections.CollectionUtils;
import org.broadleafcommerce.common.exception.ServiceException;
import org.broadleafcommerce.core.checkout.service.exception.CheckoutException;
import org.broadleafcommerce.core.order.domain.FulfillmentGroup;
import org.broadleafcommerce.core.order.domain.Order;
import org.broadleafcommerce.core.payment.domain.PaymentInfo;
import org.broadleafcommerce.core.payment.service.type.PaymentInfoType;
import org.broadleafcommerce.core.pricing.service.exception.PricingException;
import org.broadleafcommerce.core.web.checkout.model.BillingInfoForm;
import org.broadleafcommerce.core.web.checkout.model.OrderInfoForm;
import org.broadleafcommerce.core.web.checkout.model.OrderMultishipOptionForm;
import org.broadleafcommerce.core.web.checkout.model.ShippingInfoForm;
import org.broadleafcommerce.core.web.order.CartState;
import org.broadleafcommerce.profile.core.domain.CustomerAddress;
import org.broadleafcommerce.profile.web.core.CustomerState;
import org.broadleafcommerce.vendor.authorizenet.web.controller.BroadleafAuthorizeNetController;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Controller
@RequestMapping("/checkout")
public class CheckoutController extends BroadleafAuthorizeNetController {
/*
* The Checkout page for Heat Clinic will have the shipping information pre-populated
* with an address if the fulfillment group has an address and fulfillment option
* associated with it. It also assumes that there is only one payment info of type
* credit card on the order. If so, then the billing address will be pre-populated.
*/
@RequestMapping("")
public String checkout(HttpServletRequest request, HttpServletResponse response, Model model,
@ModelAttribute("orderInfoForm") OrderInfoForm orderInfoForm,
@ModelAttribute("shippingInfoForm") ShippingInfoForm shippingForm,
@ModelAttribute("billingInfoForm") BillingInfoForm billingForm, RedirectAttributes redirectAttributes) {
prepopulateCheckoutForms(CartState.getCart(), orderInfoForm, shippingForm, billingForm);
return super.checkout(request, response, model, redirectAttributes);
}
@RequestMapping(value = "/savedetails", method = RequestMethod.POST)
public String saveGlobalOrderDetails(HttpServletRequest request, Model model,
@ModelAttribute("orderInfoForm") OrderInfoForm orderInfoForm, BindingResult result) throws ServiceException {
return super.saveGlobalOrderDetails(request, model, orderInfoForm, result);
}
@RequestMapping(value="/singleship", method = RequestMethod.GET)
public String convertToSingleship(HttpServletRequest request, HttpServletResponse response, Model model) throws PricingException {
return super.convertToSingleship(request, response, model);
}
@RequestMapping(value="/singleship", method = RequestMethod.POST)
public String saveSingleShip(HttpServletRequest request, HttpServletResponse response, Model model,
@ModelAttribute("orderInfoForm") OrderInfoForm orderInfoForm,
@ModelAttribute("billingInfoForm") BillingInfoForm billingForm,
@ModelAttribute("shippingInfoForm") ShippingInfoForm shippingForm,
BindingResult result) throws PricingException, ServiceException {
prepopulateOrderInfoForm(CartState.getCart(), orderInfoForm);
return super.saveSingleShip(request, response, model, shippingForm, result);
}
@RequestMapping(value = "/multiship", method = RequestMethod.GET)
public String showMultiship(HttpServletRequest request, HttpServletResponse response, Model model,
@ModelAttribute("orderMultishipOptionForm") OrderMultishipOptionForm orderMultishipOptionForm,
BindingResult result) throws PricingException {
return super.showMultiship(request, response, model);
}
@RequestMapping(value = "/multiship", method = RequestMethod.POST)
public String saveMultiship(HttpServletRequest request, HttpServletResponse response, Model model,
@ModelAttribute("orderMultishipOptionForm") OrderMultishipOptionForm orderMultishipOptionForm,
BindingResult result) throws PricingException, ServiceException {
return super.saveMultiship(request, response, model, orderMultishipOptionForm, result);
}
@RequestMapping(value = "/add-address", method = RequestMethod.GET)
public String showMultishipAddAddress(HttpServletRequest request, HttpServletResponse response, Model model,
@ModelAttribute("addressForm") ShippingInfoForm addressForm, BindingResult result) {
return super.showMultishipAddAddress(request, response, model);
}
@RequestMapping(value = "/add-address", method = RequestMethod.POST)
public String saveMultishipAddAddress(HttpServletRequest request, HttpServletResponse response, Model model,
@ModelAttribute("addressForm") ShippingInfoForm addressForm, BindingResult result) throws ServiceException {
return super.saveMultishipAddAddress(request, response, model, addressForm, result);
}
@RequestMapping(value = "/complete", method = RequestMethod.POST)
public String completeSecureCreditCardCheckout(HttpServletRequest request, HttpServletResponse response, Model model,
@ModelAttribute("orderInfoForm") OrderInfoForm orderInfoForm,
@ModelAttribute("shippingInfoForm") ShippingInfoForm shippingForm,
@ModelAttribute("billingInfoForm") BillingInfoForm billingForm,
BindingResult result) throws CheckoutException, PricingException, ServiceException {
prepopulateCheckoutForms(CartState.getCart(), null, shippingForm, billingForm);
return super.completeSecureCreditCardCheckout(request, response, model, billingForm, result);
}
@RequestMapping(value = "/process", method = RequestMethod.POST, produces = "text/html")
public @ResponseBody String processAuthorizeNetAuthorizeAndDebit(HttpServletRequest request, HttpServletResponse response, Model model, @ModelAttribute("shippingInfoForm") ShippingInfoForm shippingForm, @ModelAttribute("billingInfoForm") BillingInfoForm billingForm) throws NoSuchAlgorithmException, UnsupportedEncodingException, PricingException, InvalidKeyException {
return super.processAuthorizeNetAuthorizeAndDebit(request, response, model);
}
protected void prepopulateOrderInfoForm(Order cart, OrderInfoForm orderInfoForm) {
if (orderInfoForm != null) {
orderInfoForm.setEmailAddress(cart.getEmailAddress());
}
}
protected void prepopulateCheckoutForms(Order cart, OrderInfoForm orderInfoForm, ShippingInfoForm shippingForm,
BillingInfoForm billingForm) {
List<FulfillmentGroup> groups = cart.getFulfillmentGroups();
prepopulateOrderInfoForm(cart, orderInfoForm);
if (CollectionUtils.isNotEmpty(groups) && groups.get(0).getFulfillmentOption() != null) {
//if the cart has already has fulfillment information
shippingForm.setAddress(groups.get(0).getAddress());
shippingForm.setFulfillmentOption(groups.get(0).getFulfillmentOption());
shippingForm.setFulfillmentOptionId(groups.get(0).getFulfillmentOption().getId());
} else {
//check for a default address for the customer
CustomerAddress defaultAddress = customerAddressService.findDefaultCustomerAddress(CustomerState.getCustomer().getId());
if (defaultAddress != null) {
shippingForm.setAddress(defaultAddress.getAddress());
shippingForm.setAddressName(defaultAddress.getAddressName());
}
}
if (cart.getPaymentInfos() != null) {
for (PaymentInfo paymentInfo : cart.getPaymentInfos()) {
if (PaymentInfoType.CREDIT_CARD.equals(paymentInfo.getType())) {
billingForm.setAddress(paymentInfo.getAddress());
}
}
}
}
@InitBinder
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
super.initBinder(request, binder);
}
}
My understanding was that the payment information would be gotten from the forms already provided by the heatclinic DemoApp. Is there something I am missing here, or do I have to add the paymentInfo form and if so how is that wired to the already provided work flow. Do I have to create a separate workflow just to handle authorize.net?
Finally, is it possible to use the billingInfoForm instead of writing a new paymentInfoForm since the information for billing and payment is the same?