svn commit: r882103 [1/2] - in /ofbiz/trunk: ./ applications/accounting/ applications/accounting/config/ applications/accounting/data/ applications/accounting/entitydef/ applications/accounting/script/org/ofbiz/accounting/payment/ applications/accounti...

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r882103 [1/2] - in /ofbiz/trunk: ./ applications/accounting/ applications/accounting/config/ applications/accounting/data/ applications/accounting/entitydef/ applications/accounting/script/org/ofbiz/accounting/payment/ applications/accounti...

jleroux@apache.org
Author: jleroux
Date: Thu Nov 19 11:01:29 2009
New Revision: 882103

URL: http://svn.apache.org/viewvc?rev=882103&view=rev
Log:
A patch from Abdullah Shaikh "SagePay payment gateway integrated" (https://issues.apache.org/jira/browse/OFBIZ-3180) - OFBIZ-3180
SagePay payment gateway integrated. All the gateway parameters are configurable using the Payment gateway configuration, also the transaction types that are available in sagepay are configurable.

I moved the httpclient httpcore jars to base/lib (also new jcip-annotations-1.0.jar)

Added:
    ofbiz/trunk/applications/accounting/servicedef/services_sagepay.xml   (with props)
    ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/sagepay/
    ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/sagepay/SagePayPaymentServices.java   (with props)
    ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/sagepay/SagePayServices.java   (with props)
    ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/sagepay/SagePayUtil.java   (with props)
    ofbiz/trunk/framework/base/lib/httpclient-4.0.jar   (with props)
    ofbiz/trunk/framework/base/lib/httpcore-4.0.1.jar   (with props)
    ofbiz/trunk/framework/base/lib/jcip-annotations-1.0.jar   (with props)
Removed:
    ofbiz/trunk/framework/testtools/lib/httpclient-4.0-beta1.jar
    ofbiz/trunk/framework/testtools/lib/httpcore-4.0-beta2.jar
Modified:
    ofbiz/trunk/.classpath
    ofbiz/trunk/applications/accounting/config/AccountingUiLabels.xml
    ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml
    ofbiz/trunk/applications/accounting/entitydef/entitymodel.xml
    ofbiz/trunk/applications/accounting/ofbiz-component.xml
    ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/payment/PaymentGatewayConfigServices.xml
    ofbiz/trunk/applications/accounting/servicedef/services_paymentgateway.xml
    ofbiz/trunk/applications/accounting/webapp/accounting/WEB-INF/controller.xml
    ofbiz/trunk/applications/accounting/widget/PaymentGatewayConfigForms.xml
    ofbiz/trunk/applications/accounting/widget/PaymentGatewayConfigScreens.xml

Modified: ofbiz/trunk/.classpath
URL: http://svn.apache.org/viewvc/ofbiz/trunk/.classpath?rev=882103&r1=882102&r2=882103&view=diff
==============================================================================
--- ofbiz/trunk/.classpath (original)
+++ ofbiz/trunk/.classpath Thu Nov 19 11:01:29 2009
@@ -141,6 +141,9 @@
     <classpathentry kind="lib" path="framework/base/lib/jpim-0.1.jar"/>
     <classpathentry kind="lib" path="framework/base/lib/freemarker-2.3.15.jar"/>
     <classpathentry kind="lib" path="framework/base/lib/owasp-esapi-full-java-1.4.jar"/>
+    <classpathentry kind="lib" path="framework/base/lib/httpcore-4.0.1.jar"/>
+    <classpathentry kind="lib" path="framework/base/lib/httpclient-4.0.jar"/>
+    <classpathentry kind="lib" path="framework/base/lib/jcip-annotations-1.0.jar"/>    
     <classpathentry kind="lib" path="framework/webapp/lib/json-lib-2.2.3-jdk15.jar"/>
     <classpathentry kind="lib" path="framework/webapp/lib/ezmorph-0.9.1.jar"/>
     <classpathentry kind="lib" path="specialpurpose/pos/lib/looks-2.0.2.jar"/>

Modified: ofbiz/trunk/applications/accounting/config/AccountingUiLabels.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/config/AccountingUiLabels.xml?rev=882103&r1=882102&r2=882103&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/config/AccountingUiLabels.xml (original)
+++ ofbiz/trunk/applications/accounting/config/AccountingUiLabels.xml Thu Nov 19 11:01:29 2009
@@ -13686,4 +13686,52 @@
         <value xml:lang="en">Batch Payments</value>
         <value xml:lang="hi_IN">भुगतान का बैच</value>
     </property>
-</resource>
+    <property key="PageTitleUpdatePaymentGatewayConfigSagePay">
+        <value xml:lang="en">Update Payment Gateway Config SagePay</value>
+    </property>
+    <property key="AccountingSagePayVendor">
+        <value xml:lang="en">Vendor Name</value>
+    </property>
+    <property key="AccountingSagePayProductionHost">
+        <value xml:lang="en">Production Host</value>
+    </property>
+    <property key="AccountingSagePayTestingHost">
+        <value xml:lang="en">Testing Host</value>
+    </property>
+    <property key="AccountingSagePayMode">
+        <value xml:lang="en">Mode</value>
+    </property>            
+    <property key="AccountingSagePayProtocolVersion">
+        <value xml:lang="en">Protocol Version</value>
+    </property>    
+    <property key="AccountingSagePayAuthenticationTransType">
+        <value xml:lang="en">Authentication Type</value>
+    </property>
+    <property key="AccountingSagePayAuthenticationUrl">
+        <value xml:lang="en">Authentication Url</value>
+    </property>
+    <property key="AccountingSagePayAuthorisationTransType">
+        <value xml:lang="en">Authorisation Type</value>
+    </property>
+    <property key="AccountingSagePayAuthorisationUrl">
+        <value xml:lang="en">Authorisation Url</value>
+    </property>
+    <property key="AccountingSagePayReleaseTransType">
+        <value xml:lang="en">Release Type</value>
+    </property>
+    <property key="AccountingSagePayReleaseUrl">
+        <value xml:lang="en">Release Url</value>
+    </property>
+    <property key="AccountingSagePayVoidUrl">
+        <value xml:lang="en">Void Url</value>
+    </property>
+    <property key="AccountingSagePayRefundUrl">
+        <value xml:lang="en">Refund Url</value>
+    </property>
+    <property key="AccountingSagePayProduction">
+        <value xml:lang="en">Production</value>
+    </property>
+    <property key="AccountingSagePayTest">
+        <value xml:lang="en">Test</value>
+    </property>
+</resource>
\ No newline at end of file

Modified: ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml?rev=882103&r1=882102&r2=882103&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml (original)
+++ ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml Thu Nov 19 11:01:29 2009
@@ -694,6 +694,10 @@
     <PaymentGroupType paymentGroupTypeId="BATCH_PAYMENT" parentTypeId="" hasTable="N" description="Batch of Payments"/>
 
     <!-- Payment Gateway Config -->
+    <PaymentGatewayConfigType paymentGatewayConfigTypeId="SAGEPAY" hasTable="N" description="SagePay Payment Gateway"/>
+    <PaymentGatewayConfig paymentGatewayConfigId="SAGEPAY_CONFIG" paymentGatewayConfigTypeId="SAGEPAY" description="SagePay Config"/>
+    <PaymentGatewaySagePay paymentGatewayConfigId="SAGEPAY_CONFIG" vendor="YOUR_VENDOR_NAME" productionHost="https://live.sagepay.com:443" testingHost="https://test.sagepay.com:443" mode="TEST" protocolVersion="2.22" authenticationTransType="DEFERRED" authenticationUrl="/gateway/service/vspdirect-register.vsp" authoriseTransType="RELEASE" authoriseUrl="/gateway/service/release.vsp" releaseTransType="ABORT" releaseUrl="/gateway/service/abort.vsp" voidUrl="/gateway/service/void.vsp" refundUrl="/gateway/service/refund.vsp"/>
+
     <PaymentGatewayConfigType paymentGatewayConfigTypeId="AUTHORIZE_NET" hasTable="N" description="Authorize Dot Net Payment Gateway"/>
     <PaymentGatewayConfig paymentGatewayConfigId="AUTHORIZE_NET_CONFIG" paymentGatewayConfigTypeId="AUTHORIZE_NET" description="Authorize Dot Net Config"/>
     <PaymentGatewayAuthorizeNet paymentGatewayConfigId="AUTHORIZE_NET_CONFIG" transactionUrl="https://certification.authorize.net/gateway/transact.dll" certificateAlias="certification.authorize.net-1" apiVersion="3.1" delimitedData="TRUE" delimiterChar="|" method="CC" emailCustomer="FALSE" emailMerchant="FALSE" testMode="TRUE" relayResponse="FALSE" tranKey="" userId="" pwd="" transDescription="OFBizAuthNet"/>

Modified: ofbiz/trunk/applications/accounting/entitydef/entitymodel.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/entitydef/entitymodel.xml?rev=882103&r1=882102&r2=882103&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/entitydef/entitymodel.xml (original)
+++ ofbiz/trunk/applications/accounting/entitydef/entitymodel.xml Thu Nov 19 11:01:29 2009
@@ -3146,6 +3146,28 @@
         <key-map field-name="paymentGatewayConfigTypeId" rel-field-name="paymentGatewayConfigTypeId"/>
       </relation>
     </entity>
+    <entity entity-name="PaymentGatewaySagePay"
+            package-name="org.ofbiz.accounting.payment"
+            title="SagePay Payment Gateway Configuration">
+      <field name="paymentGatewayConfigId" type="id-ne"></field>
+      <field name="vendor" type="short-varchar"><description>Vendor name</description></field>
+      <field name="productionHost" type="short-varchar"><description>Production Host</description></field>
+      <field name="testingHost" type="short-varchar"><description>Testing Host</description></field>
+      <field name="mode" type="short-varchar"><description>Mode (PRODUCTION/TEST)</description></field>
+      <field name="protocolVersion" type="very-short"><description>Protocol Version</description></field>
+      <field name="authenticationTransType" type="short-varchar"><description>Authentication type (PAYMENT/AUTHENTICATE/DEFERRED)</description></field>
+      <field name="authenticationUrl" type="long-varchar"><description>Authentication Url</description></field>
+      <field name="authoriseTransType" type="short-varchar"><description>Authorise type (AUTHORISE/RELEASE)</description></field>
+      <field name="authoriseUrl" type="long-varchar"><description>Authorise url</description></field>
+      <field name="releaseTransType" type="short-varchar"><description>Release type (CANCEL/ABORT)</description></field>
+      <field name="releaseUrl" type="long-varchar"><description>Release Url</description></field>
+      <field name="voidUrl" type="long-varchar"><description>Void Url</description></field>
+      <field name="refundUrl" type="long-varchar"><description>Refund Url</description></field>
+      <prim-key field="paymentGatewayConfigId"/>
+      <relation type="one" fk-name="PGSP_PGC" rel-entity-name="PaymentGatewayConfig">
+        <key-map field-name="paymentGatewayConfigId"/>
+      </relation>
+    </entity>
     <entity entity-name="PaymentGatewayAuthorizeNet"
             package-name="org.ofbiz.accounting.payment"
             title="Authorize Dot Net Payment Gateway Configuration">

Modified: ofbiz/trunk/applications/accounting/ofbiz-component.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/ofbiz-component.xml?rev=882103&r1=882102&r2=882103&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/ofbiz-component.xml (original)
+++ ofbiz/trunk/applications/accounting/ofbiz-component.xml Thu Nov 19 11:01:29 2009
@@ -68,6 +68,7 @@
     <service-resource type="model" loader="main" location="servicedef/services_olap.xml"/>
 
     <!-- Payment Processor/Gateway Service Definitions -->
+    <service-resource type="model" loader="main" location="servicedef/services_sagepay.xml"/>
     <service-resource type="model" loader="main" location="servicedef/services_authorizedotnet.xml"/>
     <service-resource type="model" loader="main" location="servicedef/services_clearcommerce.xml"/>
     <service-resource type="model" loader="main" location="servicedef/services_cybersource.xml"/>

Modified: ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/payment/PaymentGatewayConfigServices.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/payment/PaymentGatewayConfigServices.xml?rev=882103&r1=882102&r2=882103&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/payment/PaymentGatewayConfigServices.xml (original)
+++ ofbiz/trunk/applications/accounting/script/org/ofbiz/accounting/payment/PaymentGatewayConfigServices.xml Thu Nov 19 11:01:29 2009
@@ -25,7 +25,13 @@
         <set-nonpk-fields map="parameters" value-field="lookedUpValue"/>
         <store-value value-field="lookedUpValue"/>
     </simple-method>
-    
+
+    <simple-method method-name="updatePaymentGatewayConfigSagePay" short-description="Update Payment Gateway Config SagePay">
+        <entity-one entity-name="PaymentGatewaySagePay" value-field="lookedUpValue"/>
+        <set-nonpk-fields map="parameters" value-field="lookedUpValue"/>
+        <store-value value-field="lookedUpValue"/>
+    </simple-method>
+
     <simple-method method-name="updatePaymentGatewayConfigAuthorizeNet" short-description="Update Payment Gateway Config Authorize Dot Net">
         <entity-one entity-name="PaymentGatewayAuthorizeNet" value-field="lookedUpValue"/>
         <set-nonpk-fields map="parameters" value-field="lookedUpValue"/>

Modified: ofbiz/trunk/applications/accounting/servicedef/services_paymentgateway.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/servicedef/services_paymentgateway.xml?rev=882103&r1=882102&r2=882103&view=diff
==============================================================================
--- ofbiz/trunk/applications/accounting/servicedef/services_paymentgateway.xml (original)
+++ ofbiz/trunk/applications/accounting/servicedef/services_paymentgateway.xml Thu Nov 19 11:01:29 2009
@@ -30,7 +30,13 @@
         <auto-attributes entity-name="PaymentGatewayConfig" include="pk" mode="IN" optional="false"/>
         <auto-attributes entity-name="PaymentGatewayConfig" include="nonpk" mode="IN" optional="true"/>
     </service>
-    
+
+    <service name="updatePaymentGatewayConfigSagePay" engine="simple" location="component://accounting/script/org/ofbiz/accounting/payment/PaymentGatewayConfigServices.xml" invoke="updatePaymentGatewayConfigSagePay">
+        <description>Update Payment Gateway Config SagePay</description>
+        <auto-attributes entity-name="PaymentGatewaySagePay" include="pk" mode="IN" optional="false"/>
+        <auto-attributes entity-name="PaymentGatewaySagePay" include="nonpk" mode="IN" optional="true"/>
+    </service>
+
     <service name="updatePaymentGatewayConfigAuthorizeNet" engine="simple" location="component://accounting/script/org/ofbiz/accounting/payment/PaymentGatewayConfigServices.xml" invoke="updatePaymentGatewayConfigAuthorizeNet">
         <description>Update Payment Gateway Config Authorize Dot Net</description>
         <auto-attributes entity-name="PaymentGatewayAuthorizeNet" include="pk" mode="IN" optional="false"/>

Added: ofbiz/trunk/applications/accounting/servicedef/services_sagepay.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/servicedef/services_sagepay.xml?rev=882103&view=auto
==============================================================================
--- ofbiz/trunk/applications/accounting/servicedef/services_sagepay.xml (added)
+++ ofbiz/trunk/applications/accounting/servicedef/services_sagepay.xml Thu Nov 19 11:01:29 2009
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you 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.
+-->
+
+<services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/services.xsd">
+    <description>Accounting Services</description>
+    <vendor>OFBiz</vendor>
+    <version>1.0</version>
+
+    <service name="sagepayCCAuth" engine="java"
+            location="org.ofbiz.accounting.thirdparty.sagepay.SagePayPaymentServices" invoke="ccAuth">
+        <description>SagePay Payment Authorization Service</description>
+        <implements service="ccAuthInterface"/>
+    </service>
+
+    <service name="sagepayCCCapture" engine="java"
+            location="org.ofbiz.accounting.thirdparty.sagepay.SagePayPaymentServices" invoke="ccCapture">
+        <description>SagePay Payment Capture Service</description>
+        <implements service="ccCaptureInterface"/>
+    </service>
+
+    <service name="sagepayCCRelease" engine="java"
+            location="org.ofbiz.accounting.thirdparty.sagepay.SagePayPaymentServices" invoke="ccRelease">
+        <description>SagePay Payment Release</description>
+        <implements service="paymentReleaseInterface"/>
+    </service>
+
+    <service name="sagepayCCRefund" engine="java"
+            location="org.ofbiz.accounting.thirdparty.sagepay.SagePayPaymentServices" invoke="ccRefund">
+        <description>SagePay Payment Refund Service</description>
+        <implements service="paymentRefundInterface"/>
+    </service>
+
+    <service name="SagePayPaymentAuthentication" engine="java" location="org.ofbiz.accounting.thirdparty.sagepay.SagePayServices"
+         invoke="paymentAuthentication" auth="false">
+        <description>For payment authentication</description>
+        <attribute name="paymentGatewayConfigId" type="String" mode="IN" optional="true"/>
+        <attribute name="transactionType" type="String" mode="OUT" optional="false"/>
+        <attribute name="vendorTxCode" type="String" mode="INOUT" optional="false"/>
+        <attribute name="cardHolder" type="String" mode="IN" optional="false"/>
+        <attribute name="cardNumber" type="String" mode="IN" optional="false"/>
+        <attribute name="expiryDate" type="String" mode="IN" optional="false"/>
+        <attribute name="cardType" type="String" mode="IN" optional="false"/>
+        <attribute name="amount" type="String" mode="INOUT" optional="false"/>
+        <attribute name="currency" type="String" mode="IN" optional="false"/>
+        
+        <!-- All the Billing* & Delivery* fields are not mandatory in version 2.22,
+        but mandatory in version 2.23, hence making them as optional -->
+        
+        <attribute name="billingSurname" type="String" mode="IN" optional="true"/>
+        <attribute name="billingFirstnames" type="String" mode="IN" optional="true"/>
+        <attribute name="billingAddress" type="String" mode="IN" optional="false"/>
+        <attribute name="billingAddress2" type="String" mode="IN" optional="true"/>
+        <attribute name="billingCity" type="String" mode="IN" optional="true"/>
+        <attribute name="billingPostCode" type="String" mode="IN" optional="false"/>
+        <attribute name="billingCountry" type="String" mode="IN" optional="true"/>
+        <attribute name="billingState" type="String" mode="IN" optional="true"/>
+        <attribute name="billingPhone" type="String" mode="IN" optional="true"/>
+        
+        <attribute name="isBillingSameAsDelivery" type="Boolean" mode="IN" optional="true"/>
+
+        <attribute name="deliverySurname" type="String" mode="IN" optional="true"/>
+        <attribute name="deliveryFirstnames" type="String" mode="IN" optional="true"/>
+        <attribute name="deliveryAddress" type="String" mode="IN" optional="true"/>
+        <attribute name="deliveryAddress2" type="String" mode="IN" optional="true"/>
+        <attribute name="deliveryCity" type="String" mode="IN" optional="true"/>
+        <attribute name="deliveryPostCode" type="String" mode="IN" optional="true"/>
+        <attribute name="deliveryCountry" type="String" mode="IN" optional="true"/>
+        <attribute name="deliveryState" type="String" mode="IN" optional="true"/>
+        <attribute name="deliveryPhone" type="String" mode="IN" optional="true"/>
+
+        <!-- start optional parameters (optional not to the service, but to the payment gateway -->
+        <attribute name="cv2" type="String" mode="IN" optional="true"/>
+        <attribute name="startDate" type="String" mode="IN" optional="true"/>
+        <attribute name="issueNumber" type="String" mode="IN" optional="true"/>
+        <!-- end optional parameters -->
+        
+        <attribute name="basket" type="String" mode="IN" optional="true"/>
+        <attribute name="description" type="String" mode="IN" optional="false"/>
+        <attribute name="clientIPAddress" type="String" mode="IN" optional="true"/>
+        
+        <attribute name="status" type="String" mode="OUT" optional="true"/>
+        <attribute name="statusDetail" type="String" mode="OUT" optional="true"/>
+
+        <!-- start - this parameters will only be returned if the transaction is authorised -->
+        <attribute name="vpsTxId" type="String" mode="OUT" optional="true"/>
+        <attribute name="securityKey" type="String" mode="OUT" optional="true"/>
+        <attribute name="txAuthNo" type="String" mode="OUT" optional="true"/>
+        <attribute name="avsCv2" type="String" mode="OUT" optional="true"/>
+        <attribute name="addressResult" type="String" mode="OUT" optional="true"/>
+        <attribute name="postCodeResult" type="String" mode="OUT" optional="true"/>
+        <attribute name="cv2Result" type="String" mode="OUT" optional="true"/>
+        <attribute name="cavv" type="String" mode="OUT" optional="true"/>
+        <!-- end - this parameters will only be returned if the transaction is authorised -->        
+
+    </service>
+    
+    <service name="SagePayPaymentAuthorisation" engine="java" location="org.ofbiz.accounting.thirdparty.sagepay.SagePayServices"
+         invoke="paymentAuthorisation" auth="false">
+        <description>For capturing the payment</description>
+        <attribute name="paymentGatewayConfigId" type="String" mode="IN" optional="true"/>
+        <attribute name="vendorTxCode" type="String" mode="IN" optional="false"/>
+        <attribute name="vpsTxId" type="String" mode="IN" optional="true"/>
+        <attribute name="securityKey" type="String" mode="IN" optional="true"/>
+        <attribute name="txAuthNo" type="String" mode="IN" optional="true"/>
+        <attribute name="amount" type="String" mode="IN" optional="false"/>
+        <attribute name="status" type="String" mode="OUT" optional="true"/>
+        <attribute name="statusDetail" type="String" mode="OUT" optional="true"/>
+    </service>
+
+    <service name="SagePayPaymentRelease" engine="java" location="org.ofbiz.accounting.thirdparty.sagepay.SagePayServices"
+         invoke="paymentRelease" auth="false">
+        <description>For releasing (cancel) the payment</description>
+        <attribute name="paymentGatewayConfigId" type="String" mode="IN" optional="true"/>
+        <attribute name="vendorTxCode" type="String" mode="IN" optional="false"/>
+        <attribute name="vpsTxId" type="String" mode="IN" optional="false"/>
+        <attribute name="securityKey" type="String" mode="IN" optional="false"/>
+        <attribute name="txAuthNo" type="String" mode="IN" optional="false"/>
+        <attribute name="releaseAmount" type="String" mode="IN" optional="false"/>
+        <attribute name="status" type="String" mode="OUT" optional="true"/>
+        <attribute name="statusDetail" type="String" mode="OUT" optional="true"/>
+    </service>
+    
+    <service name="SagePayPaymentVoid" engine="java" location="org.ofbiz.accounting.thirdparty.sagepay.SagePayServices"
+         invoke="paymentVoid" auth="false">
+        <description>For voiding the payment</description>
+        <attribute name="paymentGatewayConfigId" type="String" mode="IN" optional="true"/>
+        <attribute name="vendorTxCode" type="String" mode="IN" optional="false"/>
+        <attribute name="vpsTxId" type="String" mode="IN" optional="false"/>
+        <attribute name="securityKey" type="String" mode="IN" optional="false"/>
+        <attribute name="txAuthNo" type="String" mode="IN" optional="false"/>
+        <attribute name="status" type="String" mode="OUT" optional="true"/>
+        <attribute name="statusDetail" type="String" mode="OUT" optional="true"/>
+    </service>
+    
+    <service name="SagePayPaymentRefund" engine="java" location="org.ofbiz.accounting.thirdparty.sagepay.SagePayServices"
+         invoke="paymentRefund" auth="false">
+        <description>For refunding the payment</description>
+        <attribute name="paymentGatewayConfigId" type="String" mode="IN" optional="true"/>
+        <attribute name="vendorTxCode" type="String" mode="IN" optional="false"/>
+        <attribute name="amount" type="String" mode="IN" optional="false"/>
+        <attribute name="currency" type="String" mode="IN" optional="false"/>
+        <attribute name="description" type="String" mode="IN" optional="false"/>
+        <attribute name="relatedVPSTxId" type="String" mode="IN" optional="false"/>
+        <attribute name="relatedVendorTxCode" type="String" mode="IN" optional="false"/>
+        <attribute name="relatedSecurityKey" type="String" mode="IN" optional="false"/>
+        <attribute name="relatedTxAuthNo" type="String" mode="IN" optional="false"/>
+        <attribute name="status" type="String" mode="OUT" optional="true"/>
+        <attribute name="statusDetail" type="String" mode="OUT" optional="true"/>
+        <attribute name="vpsTxId" type="String" mode="OUT" optional="true"/>
+        <attribute name="txAuthNo" type="String" mode="OUT" optional="true"/>
+    </service>
+
+</services>

Propchange: ofbiz/trunk/applications/accounting/servicedef/services_sagepay.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/applications/accounting/servicedef/services_sagepay.xml
------------------------------------------------------------------------------
    svn:keywords = "Date Rev Author URL Id"

Propchange: ofbiz/trunk/applications/accounting/servicedef/services_sagepay.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/sagepay/SagePayPaymentServices.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/sagepay/SagePayPaymentServices.java?rev=882103&view=auto
==============================================================================
--- ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/sagepay/SagePayPaymentServices.java (added)
+++ ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/sagepay/SagePayPaymentServices.java Thu Nov 19 11:01:29 2009
@@ -0,0 +1,521 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.ofbiz.accounting.thirdparty.sagepay;
+
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Map;
+
+import javolution.util.FastMap;
+
+import org.ofbiz.accounting.payment.PaymentGatewayServices;
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.UtilDateTime;
+import org.ofbiz.base.util.UtilFormatOut;
+import org.ofbiz.base.util.UtilMisc;
+import org.ofbiz.entity.Delegator;
+import org.ofbiz.entity.GenericEntityException;
+import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.condition.EntityCondition;
+import org.ofbiz.entity.util.EntityUtil;
+import org.ofbiz.service.DispatchContext;
+import org.ofbiz.service.GenericServiceException;
+import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceUtil;
+
+public class SagePayPaymentServices {
+    
+    public static final String module = SagePayPaymentServices.class.getName();
+
+    private static Map<String, String> buildCustomerBillingInfo(Map<String, Object> context) {
+        
+        Debug.logInfo("SagePay - Entered buildCustomerBillingInfo", module);
+        Debug.logInfo("SagePay buildCustomerBillingInfo context : " + context, module);
+        
+        Map<String, String> billingInfo = FastMap.newInstance();
+        
+        String orderId = null;
+        BigDecimal processAmount = null;
+        String currency = null;
+        String cardNumber = null;
+        String cardType = null;
+        String nameOnCard = null;
+        String expireDate = null;
+        String securityCode = null;
+        String postalCode = null;
+        String address = null;
+
+        try {
+            
+            GenericValue opp = (GenericValue) context.get("orderPaymentPreference");
+            if (opp != null) {
+                if ("CREDIT_CARD".equals(opp.getString("paymentMethodTypeId"))) {
+
+                    GenericValue creditCard = (GenericValue) context.get("creditCard");
+                    if (creditCard == null || !(opp.get("paymentMethodId").equals(creditCard.get("paymentMethodId")))) {
+                        creditCard = opp.getRelatedOne("CreditCard");
+                    }
+
+                    securityCode = opp.getString("securityCode");
+
+                    //getting billing address
+                    GenericValue billingAddress = (GenericValue) context.get("billingAddress");
+                    postalCode = billingAddress.getString("postalCode");
+                    String address2 = billingAddress.getString("address2");
+                    if (address2 == null){
+                        address2 = "";
+                    }
+                    address = billingAddress.getString("address1") + " " + address2;
+
+                    //getting card details
+                    cardNumber = creditCard.getString("cardNumber");
+                    String firstName = creditCard.getString("firstNameOnCard");
+                    String middleName = creditCard.getString("middleNameOnCard");
+                    String lastName = creditCard.getString("lastNameOnCard");
+                    if (middleName == null){
+                        middleName = "";
+                    }
+                    nameOnCard = firstName + " " + middleName + " " + lastName;
+                    cardType = creditCard.getString("cardType");
+                    if (cardType != null) {
+                        if (cardType.equals("MasterCard")) {
+                            cardType = "MC";
+                        }
+                        if (cardType.equals("VisaElectron")) {
+                            cardType = "UKE";
+                        }
+                        if (cardType.equals("DinersClub")) {
+                            cardType = "DC";
+                        }
+                        if (cardType.equals("Switch")) {
+                            cardType = "MAESTRO";
+                        }
+                    }
+                    expireDate = creditCard.getString("expireDate");
+                    String month = expireDate.substring(0,2);
+                    String year = expireDate.substring(5);
+                    expireDate = month + year;
+
+                    //getting order details
+                    orderId = UtilFormatOut.checkNull((String) context.get("orderId"));
+                    processAmount =  (BigDecimal) context.get("processAmount");
+                    currency = (String) context.get("currency");
+
+                } else {
+                    Debug.logWarning("Payment preference " + opp + " is not a credit card", module);
+                }
+            }
+        } catch (GenericEntityException ex) {
+            Debug.logError("Cannot build customer information for " + context + " due to error: " + ex.getMessage(), module);
+            return null;
+        }
+
+        billingInfo.put("orderId", orderId);
+        billingInfo.put("amount", processAmount.toString());
+        billingInfo.put("currency", currency);
+        billingInfo.put("description", orderId);
+        billingInfo.put("cardNumber", cardNumber);
+        billingInfo.put("cardHolder",  nameOnCard);
+        billingInfo.put("expiryDate", expireDate);
+        billingInfo.put("cardType", cardType);    
+        billingInfo.put("cv2", securityCode);
+        billingInfo.put("billingPostCode", postalCode);
+        billingInfo.put("billingAddress", address);
+        
+        Debug.logInfo("SagePay billingInfo : " + billingInfo, module);
+        Debug.logInfo("SagePay - Exiting buildCustomerBillingInfo", module);
+        
+        return billingInfo;
+    }
+
+    public static Map<String, Object> ccAuth(DispatchContext dctx, Map<String, Object> context) {
+        Debug.logInfo("SagePay - Entered ccAuth", module);
+        Debug.logInfo("SagePay ccAuth context : " + context, module);
+        Map<String, Object> response = null;
+
+        String orderId = (String) context.get("orderId");
+        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
+        if (null == orderPaymentPreference) {
+            response = ServiceUtil.returnError("OrderPaymentPreference for order : " + orderId + " is null : " + orderPaymentPreference);
+        } else {
+            response = processCardAuthorisationPayment(dctx, context);
+        }
+        Debug.logInfo("SagePay ccAuth response : " + response, module);
+        Debug.logInfo("SagePay - Exiting ccAuth", module);
+        return response;
+    }
+    
+
+    private static Map<String, Object> processCardAuthorisationPayment(DispatchContext ctx, Map<String, Object> context) {
+        
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+        LocalDispatcher dispatcher = ctx.getDispatcher();
+
+        Map<String, String> billingInfo = buildCustomerBillingInfo(context);
+        String paymentGatewayConfigId = (String) context.get("paymentGatewayConfigId");
+
+        try {
+
+            Map<String, Object> paymentResult = dispatcher.runSync("SagePayPaymentAuthentication",
+                    UtilMisc.toMap(
+                            "paymentGatewayConfigId", paymentGatewayConfigId,
+                            "vendorTxCode", billingInfo.get("orderId"),
+                            "cardHolder", billingInfo.get("cardHolder"),
+                            "cardNumber", billingInfo.get("cardNumber"),
+                            "expiryDate", billingInfo.get("expiryDate"),
+                            "cardType", billingInfo.get("cardType"),
+                            "cv2", billingInfo.get("cv2"),
+                            "description", billingInfo.get("description"),
+                            "amount", billingInfo.get("amount"),
+                            "currency", billingInfo.get("currency"),
+                            "billingAddress", billingInfo.get("billingAddress"),
+                            "billingPostCode", billingInfo.get("billingPostCode")
+                        )
+                    );
+
+            Debug.logInfo("SagePay - SagePayPaymentAuthentication result : " + paymentResult, module);
+
+            String transactionType = (String) paymentResult.get("transactionType");
+            String status = (String) paymentResult.get("status");
+            String statusDetail = (String) paymentResult.get("statusDetail");
+            String vpsTxId = (String) paymentResult.get("vpsTxId");
+            String securityKey = (String) paymentResult.get("securityKey");
+            String txAuthNo = (String) paymentResult.get("txAuthNo");
+            String vendorTxCode = (String) paymentResult.get("vendorTxCode");
+            String amount = (String) paymentResult.get("amount");
+
+            if (status != null && "OK".equals(status)) {
+                Debug.logInfo("SagePay - Payment authorized for order : " + vendorTxCode, module);
+                result = SagePayUtil.buildCardAuthorisationPaymentResponse(Boolean.TRUE, txAuthNo, securityKey, new BigDecimal(amount), vpsTxId, vendorTxCode, statusDetail);
+                if ("PAYMENT".equals(transactionType)) {
+                    Map<String,Object> captureResult = SagePayUtil.buildCardCapturePaymentResponse(Boolean.TRUE, txAuthNo, securityKey, new BigDecimal(amount), vpsTxId, vendorTxCode, statusDetail);
+                    result.putAll(captureResult);
+                }
+            } else if (status != null && "INVALID".equals(status)) {
+                Debug.logInfo("SagePay - Invalid authorisation request for order : " + vendorTxCode, module);
+                result = SagePayUtil.buildCardAuthorisationPaymentResponse(Boolean.FALSE, null, null, new BigDecimal("0.00"), "INVALID", vendorTxCode, statusDetail);
+            } else if (status != null && "MALFORMED".equals(status)) {
+                Debug.logInfo("SagePay - Malformed authorisation request for order : " + vendorTxCode, module);
+                result = SagePayUtil.buildCardAuthorisationPaymentResponse(Boolean.FALSE, null, null, new BigDecimal("0.00"), "MALFORMED", vendorTxCode, statusDetail);
+            } else if (status != null && "NOTAUTHED".equals(status)) {
+                Debug.logInfo("SagePay - NotAuthed authorisation request for order : " + vendorTxCode, module);
+                result = SagePayUtil.buildCardAuthorisationPaymentResponse(Boolean.FALSE, null, securityKey, new BigDecimal("0.00"), vpsTxId, vendorTxCode, statusDetail);
+            } else if (status != null && "REJECTED".equals(status)) {
+                Debug.logInfo("SagePay - Rejected authorisation request for order : " + vendorTxCode, module);
+                result = SagePayUtil.buildCardAuthorisationPaymentResponse(Boolean.FALSE, null, securityKey, new BigDecimal(amount), vpsTxId, vendorTxCode, statusDetail);
+            } else {
+                Debug.logInfo("SagePay - Invalid status " + status + " received for order : " + vendorTxCode, module);
+                result = SagePayUtil.buildCardAuthorisationPaymentResponse(Boolean.FALSE, null, null, new BigDecimal("0.00"), "ERROR", vendorTxCode, statusDetail);
+            }
+        } catch(GenericServiceException e) {
+            Debug.logError(e, "Error in calling SagePayPaymentAuthentication", module);
+            result = ServiceUtil.returnError("Exception in calling SagePayPaymentRegistration : " + e.getMessage());
+        }
+        return result;
+    }
+
+    public static Map<String, Object> ccCapture(DispatchContext ctx, Map<String, Object> context) {
+        Debug.logInfo("SagePay - Entered ccCapture", module);
+        Debug.logInfo("SagePay ccCapture context : " + context, module);
+
+        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
+        GenericValue authTransaction = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
+        context.put("authTransaction", authTransaction);
+        Map<String, Object> response = processCardCapturePayment(ctx, context);
+        
+        Debug.logInfo("SagePay ccCapture response : " + response, module);
+        Debug.logInfo("SagePay - Exiting ccCapture", module);
+        
+        return response;
+    }
+    
+    
+    private static Map<String, Object> processCardCapturePayment(DispatchContext ctx, Map<String, Object> context) {
+
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+        LocalDispatcher dispatcher = ctx.getDispatcher();
+
+        String paymentGatewayConfigId = (String) context.get("paymentGatewayConfigId");
+        GenericValue authTransaction = (GenericValue) context.get("authTransaction");
+        BigDecimal amount = (BigDecimal) context.get("captureAmount");
+        String vendorTxCode = (String) authTransaction.get("altReference");
+        String vpsTxId = (String) authTransaction.get("referenceNum");
+        String securityKey = (String) authTransaction.get("gatewayFlag");
+        String txAuthCode = (String) authTransaction.get("gatewayCode");
+
+        try {
+
+            Map<String, Object> paymentResult = dispatcher.runSync("SagePayPaymentAuthorisation",
+                    UtilMisc.toMap(
+                            "paymentGatewayConfigId", paymentGatewayConfigId,
+                            "vendorTxCode", vendorTxCode,
+                            "vpsTxId", vpsTxId,
+                            "securityKey", securityKey,
+                            "txAuthNo", txAuthCode,
+                            "amount", amount.toString()
+                        )
+                    );
+            Debug.logInfo("SagePay - SagePayPaymentAuthorisation result : " + paymentResult, module);
+            String status = (String) paymentResult.get("status");
+            String statusDetail = (String) paymentResult.get("statusDetail");
+            if (status != null && "OK".equals(status)) {
+                Debug.logInfo("SagePay Payment Released for Order : " + vendorTxCode, module);
+                result = SagePayUtil.buildCardCapturePaymentResponse(Boolean.TRUE, txAuthCode, securityKey, amount, vpsTxId, vendorTxCode, statusDetail);
+            } else {
+                Debug.logInfo("SagePay - Invalid status " + status + " received for order : " + vendorTxCode, module);
+                result = SagePayUtil.buildCardCapturePaymentResponse(Boolean.FALSE, txAuthCode, securityKey, amount, vpsTxId, vendorTxCode, statusDetail);                
+            }
+        } catch(GenericServiceException e) {
+            Debug.logError(e, "Error in calling SagePayPaymentAuthorisation", module);
+            result = ServiceUtil.returnError("Exception in calling SagePayPaymentRegistration : " + e.getMessage());
+        }
+        return result;
+    }
+    
+
+    public static Map<String, Object> ccRefund(DispatchContext ctx, Map<String, Object> context) {
+        Debug.logInfo("SagePay - Entered ccRefund", module);
+        Debug.logInfo("SagePay ccRefund context : " + context, module);
+
+        Delegator delegator = ctx.getDelegator();
+        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
+        GenericValue captureTransaction = PaymentGatewayServices.getCaptureTransaction(orderPaymentPreference);
+        if (captureTransaction == null) {
+            return ServiceUtil.returnError("No captured transaction found for the OrderPaymentPreference; cannot Refund");
+        }
+        Debug.logInfo("SagePay ccRefund captureTransaction : " + captureTransaction, module);
+        GenericValue creditCard = null;
+        try {
+            creditCard = delegator.getRelatedOne("CreditCard", orderPaymentPreference);
+        } catch (GenericEntityException e) {
+            Debug.logError(e, "Error getting CreditCard for OrderPaymentPreference : " + orderPaymentPreference, module);
+            return ServiceUtil.returnError("Unable to obtain cc information from payment preference");
+        }
+        context.put("creditCard",creditCard);
+        context.put("captureTransaction", captureTransaction);
+
+        List<GenericValue> authTransactions = PaymentGatewayServices.getAuthTransactions(orderPaymentPreference);
+
+        EntityCondition authCondition = EntityCondition.makeCondition("paymentServiceTypeEnumId", "PRDS_PAY_AUTH");
+        List<GenericValue> authTransactions1 = EntityUtil.filterByCondition(authTransactions, authCondition);
+
+        GenericValue authTransaction = EntityUtil.getFirst(authTransactions1);
+
+        Timestamp authTime = authTransaction.getTimestamp("transactionDate");
+        Calendar authCal = Calendar.getInstance();
+        authCal.setTimeInMillis(authTime.getTime());
+
+        Timestamp nowTime = UtilDateTime.nowTimestamp();
+        Calendar nowCal = Calendar.getInstance();
+        nowCal.setTimeInMillis(nowTime.getTime());
+
+        Calendar yesterday = Calendar.getInstance();
+        yesterday.set(nowCal.get(Calendar.YEAR), nowCal.get(Calendar.MONTH), nowCal.get(Calendar.DATE), 23, 59, 59);
+        yesterday.add(Calendar.DAY_OF_YEAR, -1);
+
+        Map<String, Object> response = null;
+        
+        if (authCal.before(yesterday)) {
+            Debug.logInfo("SagePay - Calling Refund for Refund", module);
+            response = processCardRefundPayment(ctx, context);
+        } else {
+
+            Calendar cal = Calendar.getInstance();
+            cal.set(nowCal.get(Calendar.YEAR), nowCal.get(Calendar.MONTH), nowCal.get(Calendar.DATE), 23, 49, 59);
+
+            if (authCal.before(cal)) {
+                Debug.logInfo("SagePay - Calling Void for Refund", module);
+                response = processCardVoidPayment(ctx, context);
+            } else {
+                Debug.logInfo("SagePay - Calling Refund for Refund", module);
+                response = processCardRefundPayment(ctx, context);
+            }
+        }
+        
+        Debug.logInfo("SagePay ccRefund response : " + response, module);
+        return response;
+    }
+
+    private static Map<String, Object> processCardRefundPayment(DispatchContext ctx, Map<String, Object> context) {
+
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+        LocalDispatcher dispatcher = ctx.getDispatcher();
+
+        String paymentGatewayConfigId = (String) context.get("paymentGatewayConfigId");
+        GenericValue captureTransaction = (GenericValue) context.get("captureTransaction");
+        BigDecimal amount = (BigDecimal) context.get("refundAmount");
+
+        String orderId = (String) captureTransaction.get("altReference");
+        orderId = "R" + orderId;
+
+        try {
+
+            Map<String, Object> paymentResult = dispatcher.runSync("SagePayPaymentRefund",
+                    UtilMisc.toMap(
+                            "paymentGatewayConfigId", paymentGatewayConfigId,
+                            "vendorTxCode", orderId,
+                            "amount", amount.toString(),
+                            "currency", "GBP",
+                            "description", orderId,
+                            "relatedVPSTxId", captureTransaction.get("referenceNum"),
+                            "relatedVendorTxCode", captureTransaction.get("altReference"),
+                            "relatedSecurityKey", captureTransaction.get("gatewayFlag"),
+                            "relatedTxAuthNo", captureTransaction.get("gatewayCode")
+                        )
+                    );
+            Debug.logInfo("SagePay - SagePayPaymentRefund result : " + paymentResult, module);
+
+            String status = (String) paymentResult.get("status");
+            String statusDetail = (String) paymentResult.get("statusDetail");
+            String vpsTxId = (String) paymentResult.get("vpsTxId");
+            String txAuthNo = (String) paymentResult.get("txAuthNo");
+
+            if (status != null && "OK".equals(status)) {
+                Debug.logInfo("SagePay Payment Refunded for Order : " + orderId, module);
+                result = SagePayUtil.buildCardRefundPaymentResponse(Boolean.TRUE, txAuthNo, amount, vpsTxId, orderId, statusDetail);
+            } else {
+                Debug.logInfo("SagePay - Invalid status " + status + " received for order : " + orderId, module);
+                result = SagePayUtil.buildCardRefundPaymentResponse(Boolean.FALSE, null, new BigDecimal("0.00"), status, orderId, statusDetail);
+            }
+
+        } catch(GenericServiceException e) {
+            Debug.logError(e, "Error in calling SagePayPaymentRefund", module);
+            result = ServiceUtil.returnError("Exception in calling SagePayPaymentRefund : " + e.getMessage());
+        }
+
+        return result;
+    }
+
+    private static Map<String, Object> processCardVoidPayment(DispatchContext ctx, Map<String, Object> context) {
+
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+        LocalDispatcher dispatcher = ctx.getDispatcher();
+
+        String paymentGatewayConfigId = (String) context.get("paymentGatewayConfigId");
+        GenericValue captureTransaction = (GenericValue) context.get("captureTransaction");
+        BigDecimal amount = (BigDecimal) context.get("refundAmount");
+        String orderId = (String) captureTransaction.get("altReference");
+
+        try {
+            
+            Map<String, Object> paymentResult = dispatcher.runSync("SagePayPaymentVoid",
+                    UtilMisc.toMap(
+                            "paymentGatewayConfigId", paymentGatewayConfigId,
+                            "vendorTxCode", captureTransaction.get("altReference"),
+                            "vpsTxId", captureTransaction.get("referenceNum"),
+                            "securityKey", captureTransaction.get("gatewayFlag"),
+                            "txAuthNo", captureTransaction.get("gatewayCode")
+                        )
+                    );
+            
+            Debug.logInfo("SagePay - SagePayPaymentVoid result : " + paymentResult, module);
+
+            String status = (String) paymentResult.get("status");
+            String statusDetail = (String) paymentResult.get("statusDetail");
+
+            if (status != null && "OK".equals(status)) {
+                Debug.logInfo("SagePay Payment Voided for Order : " + orderId, module);
+                result = SagePayUtil.buildCardVoidPaymentResponse(Boolean.TRUE, amount, "SUCCESS", orderId, statusDetail);
+            } else if (status != null && "MALFORMED".equals(status)) {
+                Debug.logInfo("SagePay - Malformed void request for order : " + orderId, module);
+                result = SagePayUtil.buildCardVoidPaymentResponse(Boolean.FALSE, new BigDecimal("0.00"), "MALFORMED", orderId, statusDetail);
+            } else if (status != null && "INVALID".equals(status)){
+                Debug.logInfo("SagePay - Invalid void request for order : " + orderId, module);
+                result = SagePayUtil.buildCardVoidPaymentResponse(Boolean.FALSE, new BigDecimal("0.00"), "INVALID", orderId, statusDetail);
+            } else if (status != null && "ERROR".equals(status)){
+                Debug.logInfo("SagePay - Error in void request for order : " + orderId, module);
+                result = SagePayUtil.buildCardVoidPaymentResponse(Boolean.FALSE, new BigDecimal("0.00"), "ERROR", orderId, statusDetail);
+            }
+
+        } catch(GenericServiceException e) {
+            Debug.logError(e, "Error in calling SagePayPaymentVoid", module);
+            result = ServiceUtil.returnError("Exception in calling SagePayPaymentVoid : " + e.getMessage());
+        }
+        return result;
+    }
+
+    public static Map<String, Object> ccRelease(DispatchContext ctx, Map<String, Object> context) {
+
+        Debug.logInfo("SagePay - Entered ccRelease", module);
+        Debug.logInfo("SagePay ccRelease context : " + context, module);
+        
+        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
+
+        GenericValue authTransaction = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
+        if (authTransaction == null) {
+            return ServiceUtil.returnError("No authorization transaction found for the OrderPaymentPreference; cannot Release");
+        }
+        context.put("authTransaction", authTransaction);
+
+        Map<String, Object> response = processCardReleasePayment(ctx, context);
+        Debug.logInfo("SagePay ccRelease response : " + response, module);
+        return response;
+    }
+
+    private static Map<String, Object> processCardReleasePayment(DispatchContext ctx, Map<String, Object> context) {
+
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+
+        LocalDispatcher dispatcher = ctx.getDispatcher();
+
+        String paymentGatewayConfigId = (String) context.get("paymentGatewayConfigId");
+        BigDecimal amount = (BigDecimal) context.get("releaseAmount");
+        
+        GenericValue authTransaction = (GenericValue) context.get("authTransaction");
+        String orderId = (String) authTransaction.get("altReference");
+        String refNum = (String) authTransaction.get("referenceNum");
+        
+        try {
+            
+            Map<String, Object> paymentResult = dispatcher.runSync("SagePayPaymentRelease",
+                    UtilMisc.toMap(
+                            "paymentGatewayConfigId", paymentGatewayConfigId,
+                            "vendorTxCode", orderId,
+                            "releaseAmount", amount.toString(),
+                            "vpsTxId", refNum,
+                            "securityKey", authTransaction.get("gatewayFlag"),
+                            "txAuthNo", authTransaction.get("gatewayCode")
+                        )
+                    );
+
+            Debug.logInfo("SagePay - SagePayPaymentRelease result : " + paymentResult, module);
+            
+            String status = (String) paymentResult.get("status");
+            String statusDetail = (String) paymentResult.get("statusDetail");
+
+            if (status != null && "OK".equals(status)) {
+                Debug.logInfo("SagePay Payment Released for Order : " + orderId, module);
+                result = SagePayUtil.buildCardReleasePaymentResponse(Boolean.TRUE, null, amount, refNum, orderId, statusDetail);
+            } else {
+                Debug.logInfo("SagePay - Invalid status " + status + " received for order : " + orderId, module);
+                result = SagePayUtil.buildCardReleasePaymentResponse(Boolean.FALSE, null, amount, refNum, orderId, statusDetail);
+            }
+
+        } catch(GenericServiceException e) {
+            Debug.logError(e, "Error in calling SagePayPaymentRelease", module);
+            result = ServiceUtil.returnError("Exception in calling SagePayPaymentRefund : " + e.getMessage());
+        }
+
+        return result;
+    }
+    
+}

Propchange: ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/sagepay/SagePayPaymentServices.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/sagepay/SagePayPaymentServices.java
------------------------------------------------------------------------------
    svn:keywords = "Date Rev Author URL Id"

Propchange: ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/sagepay/SagePayPaymentServices.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain