Author: hansbak
Date: Mon Jan 24 02:27:11 2011 New Revision: 1062608 URL: http://svn.apache.org/viewvc?rev=1062608&view=rev Log: Add the 'ideal' payment gateway, often used in the Netherlands, see http://www.ideal.nl, install instruction in the thirdparty src folder Added: ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/ ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/IdealEvents.java ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/IdealPaymentServiceTest.java ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/readme Modified: ofbiz/trunk/.classpath ofbiz/trunk/applications/accounting/config/AccountingErrorUiLabels.xml ofbiz/trunk/applications/accounting/config/AccountingUiLabels.xml ofbiz/trunk/applications/accounting/config/payment.properties ofbiz/trunk/applications/accounting/config/paymentTest.properties ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml ofbiz/trunk/applications/accounting/data/PaymentGatewayConfData.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/testdef/paymenttests.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 ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutEvents.java ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/CheckoutPayment.groovy ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/controller.xml ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/order/checkoutpayment.ftl ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/order/checkoutreview.ftl Modified: ofbiz/trunk/.classpath URL: http://svn.apache.org/viewvc/ofbiz/trunk/.classpath?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/.classpath (original) +++ ofbiz/trunk/.classpath Mon Jan 24 02:27:11 2011 @@ -202,7 +202,7 @@ <classpathentry kind="lib" path="specialpurpose/ebaystore/lib/ebaycalls.jar"/> <classpathentry kind="lib" path="specialpurpose/ebaystore/lib/ebaysdkcore.jar"/> <classpathentry kind="lib" path="specialpurpose/ebaystore/lib/helper.jar"/> - <classpathentry kind="src" path="applications/accounting/src" excluding="org/ofbiz/accounting/thirdparty/cybersource/**|org/ofbiz/accounting/thirdparty/verisign/**|org/ofbiz/accounting/thirdparty/worldpay/**|org/ofbiz/accounting/thirdparty/paypal/PayPalServices.java|org/ofbiz/accounting/thirdparty/orbital/**|org/ofbiz/accounting/thirdparty/securepay/**"/> + <classpathentry kind="src" path="applications/accounting/src" excluding="org/ofbiz/accounting/thirdparty/cybersource/**|org/ofbiz/accounting/thirdparty/verisign/**|org/ofbiz/accounting/thirdparty/worldpay/**|org/ofbiz/accounting/thirdparty/paypal/PayPalServices.java|org/ofbiz/accounting/thirdparty/orbital/**|org/ofbiz/accounting/thirdparty/securepay/**|org/ofbiz/accounting/thirdparty/ideal/**"/> <classpathentry kind="src" path="applications/content/src" excluding="org/ofbiz/content/openoffice/|org/ofbiz/content/report/"/> <classpathentry kind="src" path="applications/manufacturing/src"/> <classpathentry kind="src" path="applications/marketing/src"/> Modified: ofbiz/trunk/applications/accounting/config/AccountingErrorUiLabels.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/config/AccountingErrorUiLabels.xml?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/accounting/config/AccountingErrorUiLabels.xml (original) +++ ofbiz/trunk/applications/accounting/config/AccountingErrorUiLabels.xml Mon Jan 24 02:27:11 2011 @@ -505,4 +505,40 @@ <value xml:lang="it">Problema nel ricavare la testata ordine</value> <value xml:lang="pt">Problemas Obtendo OrderHeader</value> </property> + <property key="idealEvents.failedToExecuteServiceCreatePaymentFromPreference"> + <value xml:lang="en">Failed To Execute Service CreatePaymentFromPreference</value> + <value xml:lang="fr">Ãchec sur l'execution du service de création d'un payment suivant les préférence (CreatePaymentFromPreference)</value> + <value xml:lang="hi_IN">सरà¥à¤µà¤¿à¤¸ CreatePaymentFromPreference पर ठमल(execute) à¤à¤°à¤¨à¥ मà¥à¤ ठसफल</value> + <value xml:lang="it">Fallita esecuzione servizio CreatePaymentFromPreference</value> + </property> + <property key="idealEvents.noValidOrderIdReturned"> + <value xml:lang="en">No Valid OrderId Returned</value> + <value xml:lang="fr">Référence commande retournée n'est pas valide</value> + <value xml:lang="hi_IN">मानà¥à¤¯ OrderId वापस नहà¥à¤ लà¥à¤à¤¾</value> + <value xml:lang="it">Nessun numero ordine restituito</value> + </property> + <property key="idealEvents.problemsConnectingWithIdeal"> + <value xml:lang="en">Problems Connecting With iDEAL</value> + <value xml:lang="fr">Problème rencontré dans la connexion avec iDEAL</value> + <value xml:lang="hi_IN">iDEAL à¤à¥ साथ à¤à¥à¤¡à¤¼à¤¨à¥ मà¥à¤ समसà¥à¤¯à¤¾</value> + <value xml:lang="it">Problema nella connessione con iDEAL</value> + </property> + <property key="idealEvents.problemsGettingAuthenticationUser"> + <value xml:lang="en">Problems Getting Authentication User</value> + <value xml:lang="fr">Problème sur l'authentification de l'utilisateur</value> + <value xml:lang="hi_IN">à¤à¤ªà¤¯à¥à¤à¤à¤°à¥à¤¤à¤¾(user) à¤à¥ पà¥à¤°à¤®à¤¾à¤£à¥à¤à¤°à¤£ मà¥à¤ समसà¥à¤¯à¤¾à¤à¤ हॠरहà¥</value> + <value xml:lang="it">Problema durante l'autenticazione utente</value> + </property> + <property key="idealEvents.problemsGettingMerchantConfiguration"> + <value xml:lang="en">Problems Getting Merchant Configuration</value> + <value xml:lang="fr">Problème de récupération de la configuration marchand</value> + <value xml:lang="hi_IN">वà¥à¤¯à¤¾à¤ªà¤¾à¤°à¥ विनà¥à¤¯à¤¾à¤¸ मà¥à¤ समसà¥à¤¯à¤¾à¤à¤ हॠरहà¥</value> + <value xml:lang="it">Problema nel ricavare la configurazione del negoziante</value> + </property> + <property key="idealEvents.problemsGettingOrderHeader"> + <value xml:lang="en">Problems Getting OrderHeader</value> + <value xml:lang="fr">Problème de récupération de la commande</value> + <value xml:lang="hi_IN">OrderHeader मà¥à¤ समसà¥à¤¯à¤¾à¤à¤ हॠरहà¥</value> + <value xml:lang="it">Problema nel ricavare la testata ordine</value> + </property> </resource> Modified: ofbiz/trunk/applications/accounting/config/AccountingUiLabels.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/config/AccountingUiLabels.xml?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/accounting/config/AccountingUiLabels.xml (original) +++ ofbiz/trunk/applications/accounting/config/AccountingUiLabels.xml Mon Jan 24 02:27:11 2011 @@ -17182,4 +17182,32 @@ <value xml:lang="zh">æµè§äº¤æè®°å½</value> <value xml:lang="zh_TW">ç覽交æè¨é</value> </property> + <property key="PageTitleUpdatePaymentGatewayConfigiDEAL"> + <value xml:lang="en">Update Payment Gateway Config iDEAL</value> + <value xml:lang="hi_IN">à¤à¥à¤à¤¤à¤¾à¤¨ à¤à¥à¤à¤µà¥ विनà¥à¤¯à¤¾à¤¸ iDEAL à¤à¤¨à¥à¤¨à¤¤ à¤à¤°à¥</value> + <value xml:lang="it">Aggiorna configurazione gateway pagamento iDEAL</value> + </property> + <property key="AccountingPayWithiDEAL"> + <value xml:lang="cs">Platba prostÅednictvÃm iDEAL</value> + <value xml:lang="de">Bezahlung mit iDEAL</value> + <value xml:lang="en">Pay With iDEAL</value> + <value xml:lang="es">Pagar con iDEAL</value> + <value xml:lang="fr">Paiement avec iDEAL</value> + <value xml:lang="it">Paga con iDEAL</value> + <value xml:lang="ja">Pay With iDEAL</value> + <value xml:lang="nl">Betaal met iDEAL</value> + <value xml:lang="pt_PT">Pagar Com iDEAL</value> + <value xml:lang="ro">Plateste cu iDEAL</value> + <value xml:lang="ru">ÐлаÑиÑÑ ÑеÑез iDEAL</value> + <value xml:lang="th">à¸à¸³à¸£à¸°à¹à¸à¸´à¸à¸à¹à¸²à¸ iDEAL</value> + </property> + <property key="AccountingPaymentReceiveViaiDEAL"> + <value xml:lang="de">Zahlung über iDEAL erhalten</value> + <value xml:lang="en">Payment receive via iDEAL</value> + <value xml:lang="hi_IN">à¤à¥à¤à¤¤à¤¾à¤¨ iDEAL à¤à¥ माधà¥à¤¯à¤® सॠपà¥à¤°à¤¾à¤ªà¥à¤¤</value> + <value xml:lang="it">Pagamento ricevuto da iDEAL</value> + </property> + <property key="IdealSuccessFull"> + <value xml:lang="en">The transaction has been successfully.</value> + </property> </resource> Modified: ofbiz/trunk/applications/accounting/config/payment.properties URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/config/payment.properties?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/accounting/config/payment.properties (original) +++ ofbiz/trunk/applications/accounting/config/payment.properties Mon Jan 24 02:27:11 2011 @@ -400,3 +400,51 @@ payment.securepay.serverurl=https://api. #Enable rounds the currency amount to .00 (Y For test server / N for live server) payment.securepay.enableamountround=N + +############################################ +# iDEAL Configuration +############################################ + +## Account information +# Id van de webshop, door de acceptant te verkrijgen via het iDEAL Dashboard +merchantId= + +# Sub Id van de webshop, alleen te wijzigen na overleg met de acquirer +merchantSubId=0 + +# URL van de pagina in de webshop waarnaar de consument wordt geredirect na de iDEAL transactie +#merchantReturnURL=http://[yourServerName]/ecommerce/control/payPalNotify +merchantReturnURL=http://localhost:8080/ecommerce/control/idealNotify + +## acquirer attributes +# URL van de acquirer van de acceptant; niet wijzigen +# https://idealtest.secure-ing.com/ideal/iDeal voor test +# https://ideal.secure-ing.com/ideal/iDeal voor productie +acquirerURL=https://idealtest.secure-ing.com/ideal/iDeal + +# Connection timeout in seconds +# Default:10 seconds +acquirerTimeout=10 + +# Vervaltijd per transactie; zie paragraaf 3.3.1 van het document +# iDEAL_010 standaarden voor de toegestane waarden en de default +# Default: If not set the issuer will use the default value of PT1H (one hour) +expirationPeriod=PT1H + +## crypto attributes +# Naam van de acceptant-organisatie zoals opgegeven tijdens +# de creatie van het certificaat +privateCert= + +# Keystore File and Password of the merchant certificate +# used for signing requests. See Ideal Advanced Java +# integration manual for details. +# Note: file must be available on the classpath! +merchantKeyStoreFilename= +merchantKeyStorePassword= + +# Truststore File and Password with the acquirer public +# key used for verifying acquirer responses. +# Note: file must be available on the classpath! +acquirerKeyStoreFilename=acquirer.keystore +acquirerKeyStorePassword={xor}MiYPPiwsKDAtOw== Modified: ofbiz/trunk/applications/accounting/config/paymentTest.properties URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/config/paymentTest.properties?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/accounting/config/paymentTest.properties (original) +++ ofbiz/trunk/applications/accounting/config/paymentTest.properties Mon Jan 24 02:27:11 2011 @@ -66,3 +66,50 @@ payment.securepay.serverurl=https://test #Enable rounds the currency amount to .00 (Y For test server / N for live server) payment.securepay.enableamountround=Y +############################################ +# iDEAL Test Configuration +############################################ + +## Account information +# Id van de webshop, door de acceptant te verkrijgen via het iDEAL Dashboard +merchantId=xxxxxxx + +# Sub Id van de webshop, alleen te wijzigen na overleg met de acquirer +merchantSubId=0 + +# URL van de pagina in de webshop waarnaar de consument wordt geredirect na de iDEAL transactie +#merchantReturnURL=http://[yourServerName]/ecommerce/control/payPalNotify +merchantReturnURL=http://localhost:8080/ecommerce/control/idealNotify + +## acquirer attributes +# URL van de acquirer van de acceptant; niet wijzigen +# https://idealtest.secure-ing.com/ideal/iDeal voor test +# https://ideal.secure-ing.com/ideal/iDeal voor productie +acquirerURL=https://idealtest.secure-ing.com/ideal/iDeal + +# Connection timeout in seconds +# Default:10 seconds +acquirerTimeout=10 + +# Vervaltijd per transactie; zie paragraaf 3.3.1 van het document +# iDEAL_010 standaarden voor de toegestane waarden en de default +# Default: If not set the issuer will use the default value of PT1H (one hour) +expirationPeriod=PT1H + +## crypto attributes +# Naam van de acceptant-organisatie zoals opgegeven tijdens +# de creatie van het certificaat +privateCert=acquirer.keystore + +# Keystore File and Password of the merchant certificate +# used for signing requests. See Ideal Advanced Java +# integration manual for details. +# Note: file must be available on the classpath! +merchantKeyStoreFilename=merchant.keystore +merchantKeyStorePassword=xxxxxxx + +# Truststore File and Password with the acquirer public +# key used for verifying acquirer responses. +# Note: file must be available on the classpath! +acquirerKeyStoreFilename=acquirer.keystore +acquirerKeyStorePassword=xxxxxxx Modified: ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml (original) +++ ofbiz/trunk/applications/accounting/data/AccountingTypeData.xml Mon Jan 24 02:27:11 2011 @@ -674,6 +674,7 @@ under the License. <PaymentMethodType description="Offline Payment" paymentMethodTypeId="EXT_OFFLINE"/> <PaymentMethodType description="PayPal" paymentMethodTypeId="EXT_PAYPAL"/> <PaymentMethodType description="RBS WorldPay" paymentMethodTypeId="EXT_WORLDPAY"/> + <PaymentMethodType description="iDEAL" paymentMethodTypeId="EXT_IDEAL"/> <PaymentType description="Disbursement" hasTable="N" parentTypeId="" paymentTypeId="DISBURSEMENT"/> <PaymentType description="Customer Refund" hasTable="N" parentTypeId="DISBURSEMENT" paymentTypeId="CUSTOMER_REFUND"/> <!-- a refund TO the customer --> @@ -820,11 +821,11 @@ under the License. <CustomMethod customMethodId="PAYPAL_RELEASE_PFP" customMethodTypeId="PAYPAL_RELEASE" customMethodName="payflowPayPalVoid" description="Payflow PayPal Order release"/> <CustomMethod customMethodId="PAYPAL_RELEASE" customMethodTypeId="PAYPAL_RELEASE" customMethodName="payPalVoid" description="PayPal Order Release"/> - + <CustomMethod customMethodId="CC_CHARGE_EWAY" customMethodTypeId="CC_AUTH" customMethodName="ewayCharge" description="eWay CC Charge"/> <CustomMethod customMethodId="CC_REFUND_EWAY" customMethodTypeId="CC_REFUND" customMethodName="ewayRefund" description="eWay CC Refund"/> <CustomMethod customMethodId="CC_RELEASE_EWAY" customMethodTypeId="CC_RELEASE" customMethodName="ewayRelease" description="eWay CC Release"/> - + <CustomMethod customMethodId="SECURE_AUTH_OFBIZ" customMethodTypeId="CC_AUTH" customMethodName="ofbScAuthorize" description="SecurePay payment authorize"/> <CustomMethod customMethodId="SECURE_CAPTURE_OFBIZ" customMethodTypeId="CC_CAPTURE" customMethodName="ofbScCapture" description="SecurePay payment capture"/> <CustomMethod customMethodId="SECURE_REFUND_OFBIZ" customMethodTypeId="CC_REFUND" customMethodName="ofbScRefund" description="SecurePay payment refund"/> Modified: ofbiz/trunk/applications/accounting/data/PaymentGatewayConfData.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/data/PaymentGatewayConfData.xml?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/accounting/data/PaymentGatewayConfData.xml (original) +++ ofbiz/trunk/applications/accounting/data/PaymentGatewayConfData.xml Mon Jan 24 02:27:11 2011 @@ -56,8 +56,12 @@ under the License. <PaymentGatewayConfigType paymentGatewayConfigTypeId="ORBITAL" hasTable="N" description="Orbital Payment Gateway"/> <PaymentGatewayConfig paymentGatewayConfigId="ORBITAL_CONFIG" paymentGatewayConfigTypeId="ORBITAL" description="Orbital Config"/> <PaymentGatewayOrbital paymentGatewayConfigId="ORBITAL_CONFIG" username="ofbizuser" connectionPassword="ofbizpwd" merchantId="785240009879" engineClass="com.paymentech.orbital.sdk.engine.https.HttpsEngine" hostName="orbitalvar1.paymentech.net" port="443" hostNameFailover="orbitalvar2.paymentech.net" portFailover="443" connectionTimeoutSeconds="90" readTimeoutSeconds="90" authorizationURI="/authorize" sdkVersion="PaymentechSDK_6.3.0" sslSocketFactory="default" responseType="gateway"/> - + <PaymentGatewayConfigType paymentGatewayConfigTypeId="SECUREPAY" hasTable="N" description="SecurePay Payment Gateway"/> <PaymentGatewayConfig paymentGatewayConfigId="SECUREPAY_CONFIG" paymentGatewayConfigTypeId="SECUREPAY" description="SecurePay Config"/> - <PaymentGatewaySecurePay paymentGatewayConfigId="SECUREPAY_CONFIG" merchantId="[SecurePay MerchantID]" pwd="[SecurePay Password]" serverURL="[SecurePay serverURL]" processTimeout="80" enableAmountRound="N"/> + <PaymentGatewaySecurePay paymentGatewayConfigId="SECUREPAY_CONFIG" merchantId="[SecurePay MerchantID]" pwd="[SecurePay Password]" serverURL="[SecurePay serverURL]" processTimeout="80" enableAmountRound="N"/> + + <PaymentGatewayConfigType paymentGatewayConfigTypeId="IDEAL" hasTable="N" description="iDEAL Payment Gateway"/> + <PaymentGatewayConfig paymentGatewayConfigId="IDEAL_CONFIG" paymentGatewayConfigTypeId="IDEAL" description="iDEAL Config"/> + <PaymentGatewayiDEAL paymentGatewayConfigId="IDEAL_CONFIG" merchantId="[iDEAL MerchantID]" merchantSubId="[iDEAL MerchantSubID]" merchantReturnURL="[iDEAL MerchantReturnURL]" acquirerURL="[iDEAL AcquirerURL]" acquirerTimeout="10" privateCert="[iDEAL PrivateCert]" acquirerKeyStoreFilename="[iDEAL AcquirerKeyStoreFilename]" acquirerKeyStorePassword="[iDEAL AcquirerKeyStorePassword]" merchantKeyStoreFilename="[iDEAL MerchantKeyStoreFilename]" merchantKeyStorePassword="[iDEAL MerchantKeyStorePassword]" expirationPeriod="[iDEAL ExpirationPeriod]"/> </entity-engine-xml> Modified: ofbiz/trunk/applications/accounting/entitydef/entitymodel.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/entitydef/entitymodel.xml?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/accounting/entitydef/entitymodel.xml (original) +++ ofbiz/trunk/applications/accounting/entitydef/entitymodel.xml Mon Jan 24 02:27:11 2011 @@ -3441,6 +3441,26 @@ under the License. <key-map field-name="paymentGatewayConfigId"/> </relation> </entity> + <entity entity-name="PaymentGatewayiDEAL" + package-name="org.ofbiz.accounting.payment" + title="iDEAL Payment Gateway Config"> + <field name="paymentGatewayConfigId" type="id-ne"></field> + <field name="merchantId" type="value"><description>The ID of the webshop, received by the acceptor during the registration process</description></field> + <field name="merchantSubId" type="value"><description>SubID of the webshop, default value = 0 (zero); only to be changed in consultation with the acquirer</description></field> + <field name="merchantReturnURL" type="value"><description>URL of the page in the webshop to which the consumer is redirected after an iDEAL transaction. This value can be overruled as necessary in the webshop implementation</description></field> + <field name="acquirerURL" type="value"><description>URL of the acceptorâs acquirer; the following prescribed values apply to ING</description></field> + <field name="acquirerTimeout" type="value"><description>Number of seconds (default = 10) of waiting time for a response from the iDEAL services. If no response is received during that time, an exception is displayed</description></field> + <field name="privateCert" type="value"><description>Name of the acceptorâs organization as given during the creation of his or her own certificate. See section 0 for more information about the acceptorâs certificate</description></field> + <field name="acquirerKeyStoreFilename" type="value"><description>Keystore file and acquirerâs password</description></field> + <field name="acquirerKeyStorePassword" type="value" encrypt="true"><description>Password of the Acquirer keystore</description></field> + <field name="merchantKeyStoreFilename" type="value"><description>Keystore file and merchantâs password</description></field> + <field name="merchantKeyStorePassword" type="value" encrypt="true"><description>Password of the Merchant keystore</description></field> + <field name="expirationPeriod" type="value"><description>Expiration period of the transaction</description></field> + <prim-key field="paymentGatewayConfigId"/> + <relation type="one" fk-name="PGID_PGC" rel-entity-name="PaymentGatewayConfig"> + <key-map field-name="paymentGatewayConfigId"/> + </relation> + </entity> <entity entity-name="PaymentGatewayRespMsg" package-name="org.ofbiz.accounting.payment" Modified: ofbiz/trunk/applications/accounting/ofbiz-component.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/ofbiz-component.xml?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/accounting/ofbiz-component.xml (original) +++ ofbiz/trunk/applications/accounting/ofbiz-component.xml Mon Jan 24 02:27:11 2011 @@ -29,6 +29,7 @@ under the License. <classpath type="jar" location="lib/cybersource/*"/> <classpath type="jar" location="lib/worldpay/*"/> <classpath type="dir" location="lib/worldpay"/> + <classpath type="dir" location="ideal"/> <entity-resource type="model" reader-name="main" loader="main" location="entitydef/entitymodel.xml"/> <entity-resource type="model" reader-name="main" loader="main" location="entitydef/entitymodel_reports.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=1062608&r1=1062607&r2=1062608&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 Mon Jan 24 02:27:11 2011 @@ -79,4 +79,10 @@ under the License. <set-nonpk-fields map="parameters" value-field="lookedUpValue"/> <store-value value-field="lookedUpValue"/> </simple-method> + + <simple-method method-name="updatePaymentGatewayConfigiDEAL" short-description="Update Payment Gateway Config iDEAL"> + <entity-one entity-name="PaymentGatewayiDEAL" value-field="lookedUpValue"/> + <set-nonpk-fields map="parameters" value-field="lookedUpValue"/> + <store-value value-field="lookedUpValue"/> + </simple-method> </simple-methods> Modified: ofbiz/trunk/applications/accounting/servicedef/services_paymentgateway.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/servicedef/services_paymentgateway.xml?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/accounting/servicedef/services_paymentgateway.xml (original) +++ ofbiz/trunk/applications/accounting/servicedef/services_paymentgateway.xml Mon Jan 24 02:27:11 2011 @@ -88,5 +88,11 @@ under the License. <service name="updatePaymentGatewayConfigEway" engine="entity-auto" invoke="update" default-entity-name="PaymentGatewayEway" auth="true"> <auto-attributes mode="IN" include="pk" optional="false"/> <auto-attributes mode="IN" include="nonpk" optional="true"/> - </service> + </service> + + <service name="updatePaymentGatewayConfigiDEAL" engine="simple" location="component://accounting/script/org/ofbiz/accounting/payment/PaymentGatewayConfigServices.xml" invoke="updatePaymentGatewayConfigiDEAL"> + <description>Update Payment Gateway Config iDEAL</description> + <auto-attributes entity-name="PaymentGatewayiDEAL" include="pk" mode="IN" optional="false"/> + <auto-attributes entity-name="PaymentGatewayiDEAL" include="nonpk" mode="IN" optional="true"/> + </service> </services> Added: ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/IdealEvents.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/IdealEvents.java?rev=1062608&view=auto ============================================================================== --- ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/IdealEvents.java (added) +++ ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/IdealEvents.java Mon Jan 24 02:27:11 2011 @@ -0,0 +1,453 @@ +/******************************************************************************* + * 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.ideal; + +import java.io.IOException; +import java.math.BigDecimal; +import java.sql.Timestamp; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import javolution.util.FastList; +import javolution.util.FastMap; + +import org.ofbiz.base.util.Debug; +import org.ofbiz.base.util.StringUtil; +import org.ofbiz.base.util.UtilDateTime; +import org.ofbiz.base.util.UtilHttp; +import org.ofbiz.base.util.UtilMisc; +import org.ofbiz.base.util.UtilNumber; +import org.ofbiz.base.util.UtilProperties; +import org.ofbiz.base.util.UtilValidate; +import org.ofbiz.entity.Delegator; +import org.ofbiz.entity.GenericEntityException; +import org.ofbiz.entity.GenericValue; +import org.ofbiz.entity.transaction.GenericTransactionException; +import org.ofbiz.entity.transaction.TransactionUtil; +import org.ofbiz.order.order.OrderChangeHelper; +import org.ofbiz.product.store.ProductStoreWorker; +import org.ofbiz.service.GenericServiceException; +import org.ofbiz.service.LocalDispatcher; +import org.ofbiz.service.ModelService; + +import com.ing.ideal.connector.IdealConnector; +import com.ing.ideal.connector.IdealException; +import com.ing.ideal.connector.Issuer; +import com.ing.ideal.connector.Issuers; +import com.ing.ideal.connector.Transaction; + + +public class IdealEvents { + + public static final String resource = "AccountingUiLabels"; + public static final String resourceErr = "AccountingErrorUiLabels"; + public static final String commonResource = "CommonUiLabels"; + public static final String module = IdealEvents.class.getName(); + private static int decimals = UtilNumber.getBigDecimalScale("invoice.decimals"); + private static int rounding = UtilNumber.getBigDecimalRoundingMode("invoice.rounding"); + + /** Initiate iDEAL Request */ + public static String callIdeal(HttpServletRequest request, HttpServletResponse response) { + Locale locale = UtilHttp.getLocale(request); + Delegator delegator = (Delegator) request.getAttribute("delegator"); + + // get the orderId + String orderId = (String) request.getAttribute("orderId"); + String issuerId = (String) request.getAttribute("issuerId"); + + // get the order header + GenericValue orderHeader = null; + List<GenericValue> orderItemList = null; + try { + orderHeader = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap("orderId", orderId)); + orderItemList = delegator.findByAnd("OrderItem", UtilMisc.toMap("orderId", orderId)); + } catch (GenericEntityException e) { + Debug.logError(e, "Cannot get the order header for order: " + orderId, module); + request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.problemsGettingOrderHeader", locale)); + return "error"; + } + + // get the order total + BigDecimal orderTotal = orderHeader.getBigDecimal("grandTotal"); + + // get the product store + GenericValue productStore = ProductStoreWorker.getProductStore(request); + + if (productStore == null) { + Debug.logError("ProductStore is null", module); + request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.problemsGettingMerchantConfiguration", locale)); + return "error"; + } + + // get the payment properties file + GenericValue paymentConfig = ProductStoreWorker.getProductStorePaymentSetting(delegator, productStore.getString("productStoreId"), "EXT_IDEAL", null, true); + String configString = null; + String paymentGatewayConfigId = null; + if (paymentConfig != null) { + paymentGatewayConfigId = paymentConfig.getString("paymentGatewayConfigId"); + configString = paymentConfig.getString("paymentPropertiesPath"); + } + + if (configString == null) { + configString = "payment.properties"; + } + + String merchantId = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "merchantId", configString, "merchantId"); + String merchantSubId = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "merchantSubId", configString, "merchantSubId"); + String merchantReturnURL = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "merchantReturnURL", configString, "merchantReturnURL"); + String acquirerURL = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "acquirerURL", configString, "acquirerURL"); + String acquirerTimeout = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "acquirerTimeout", configString, "acquirerTimeout"); + String privateCert = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "privateCert", configString, "privateCert"); + String acquirerKeyStoreFilename = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "acquirerKeyStoreFilename", configString, "acquirerKeyStoreFilename"); + String acquirerKeyStorePassword = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "acquirerKeyStorePassword", configString, "acquirerKeyStorePassword"); + String merchantKeyStoreFilename = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "merchantKeyStoreFilename", configString, "merchantKeyStoreFilename"); + String merchantKeyStorePassword = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "merchantKeyStorePassword", configString, "merchantKeyStorePassword"); + String expirationPeriod = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "expirationPeriod", configString, "expirationPeriod"); + + if (UtilValidate.isEmpty(merchantId) + || UtilValidate.isEmpty(merchantReturnURL) + || UtilValidate.isEmpty(privateCert) + || UtilValidate.isEmpty(merchantKeyStoreFilename) + || UtilValidate.isEmpty(merchantKeyStoreFilename)) { + Debug.logError("Payment properties is not configured properly, some notify URL from iDEAL is not correctly defined!", module); + request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.problemsGettingMerchantConfiguration", locale)); + return "error"; + } + + List<String> descriptionList = FastList.newInstance(); + for (GenericValue orderItem : orderItemList) { + if (UtilValidate.isNotEmpty(orderItem.get("itemDescription"))){ + descriptionList.add((String) orderItem.get("itemDescription")); + } + } + + String orderDescription = StringUtil.join(descriptionList, ","); + String amount = orderTotal.setScale(decimals, rounding).movePointRight(2).toPlainString(); + + String redirectString = null; + + try { + IdealConnector connector = new IdealConnector("payment"); + Transaction transaction = new Transaction(); + transaction.setIssuerID(issuerId); + transaction.setAmount(amount); + transaction.setPurchaseID(orderId); + transaction.setDescription(orderDescription); + + String returnURL = merchantReturnURL + "?orderId=" + orderId; + Random random = new Random(); + String EntranceCode = Long.toString(Math.abs(random.nextLong()), 36); + transaction.setEntranceCode(EntranceCode); + transaction.setMerchantReturnURL(returnURL); + Transaction trx = connector.requestTransaction(transaction); + redirectString = trx.getIssuerAuthenticationURL(); + request.getSession().setAttribute("purchaseID", orderId); + request.getSession().setAttribute("payAmount", orderTotal.toPlainString()); + } catch (IdealException ex) { + Debug.logError(ex.getMessage(), module); + request.setAttribute("_ERROR_MESSAGE_", ex.getConsumerMessage()); + return "error"; + } + + // redirect to iDEAL + try { + response.sendRedirect(redirectString); + } catch (IOException e) { + Debug.logError(e, "Problems redirecting to iDEAL", module); + request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.problemsConnectingWithIdeal", locale)); + return "error"; + } + + return "success"; + } + + /** iDEAL notification */ + public static String idealNotify(HttpServletRequest request, HttpServletResponse response) { + Locale locale = UtilHttp.getLocale(request); + Delegator delegator = (Delegator) request.getAttribute("delegator"); + LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher"); + GenericValue userLogin = (GenericValue) request.getSession().getAttribute("userLogin"); + Map <String, Object> parametersMap = UtilHttp.getParameterMap(request); + String transactionId = request.getParameter("trxid"); + Set<String> keySet = parametersMap.keySet(); + Iterator<String> i = keySet.iterator(); + while (i.hasNext()) { + String name = (String) i.next(); + String value = request.getParameter(name); + Debug.logError("### Param: " + name + " => " + value, module); + } + + String orderId = null; + String paymentStatus = null; + try { + IdealConnector connector = new IdealConnector("payment"); + Transaction transaction = connector.requestTransactionStatus(transactionId); + orderId = transaction.getPurchaseID(); + if (orderId == null) { + orderId = (String) request.getSession().getAttribute("purchaseID"); + } + String payAmount = transaction.getAmount(); + if (payAmount == null) { + payAmount = (String) request.getSession().getAttribute("payAmount"); + } + paymentStatus = transaction.getStatus(); + request.setAttribute("transactionId", transactionId); + request.setAttribute("paymentStatus", paymentStatus); + request.setAttribute("paymentAmount", payAmount); + } catch (IdealException ex) { + Debug.logError(ex.getMessage(), module); + request.setAttribute("_ERROR_MESSAGE_", ex.getConsumerMessage()); + return "error"; + } + + // get the user + if (userLogin == null) { + String userLoginId = "system"; + try { + userLogin = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", userLoginId), false); + } catch (GenericEntityException e) { + Debug.logError(e, "Cannot get UserLogin for: " + userLoginId + "; cannot continue", module); + request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.problemsGettingAuthenticationUser", locale)); + return "error"; + } + } + // get the order header + GenericValue orderHeader = null; + if (UtilValidate.isNotEmpty(orderId)) { + try { + orderHeader = delegator.findOne("OrderHeader", UtilMisc.toMap("orderId", orderId), false); + } catch (GenericEntityException e) { + Debug.logError(e, "Cannot get the order header for order: " + orderId, module); + request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.problemsGettingOrderHeader", locale)); + return "error"; + } + } else { + Debug.logError("iDEAL did not callback with a valid orderId!", module); + request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.noValidOrderIdReturned", locale)); + return "error"; + } + if (orderHeader == null) { + Debug.logError("Cannot get the order header for order: " + orderId, module); + request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.problemsGettingOrderHeader", locale)); + return "error"; + } + + // attempt to start a transaction + boolean okay = true; + boolean beganTransaction = false; + try { + beganTransaction = TransactionUtil.begin(); + // authorized + if ("Success".equals(paymentStatus)) { + okay = OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId); + // cancelled + } else if ("Cancelled".equals(paymentStatus)) { + okay = OrderChangeHelper.cancelOrder(dispatcher, userLogin, orderId); + } + if (okay) { + // set the payment preference + okay = setPaymentPreferences(delegator, dispatcher, userLogin, orderId, request); + } + } catch (Exception e) { + String errMsg = "Error handling iDEAL notification"; + Debug.logError(e, errMsg, module); + try { + TransactionUtil.rollback(beganTransaction, errMsg, e); + } catch (GenericTransactionException gte2) { + Debug.logError(gte2, "Unable to rollback transaction", module); + } + } finally { + if (!okay) { + try { + TransactionUtil.rollback(beganTransaction, "Failure in processing iDEAL callback", null); + } catch (GenericTransactionException gte) { + Debug.logError(gte, "Unable to rollback transaction", module); + } + } else { + try { + TransactionUtil.commit(beganTransaction); + } catch (GenericTransactionException gte) { + Debug.logError(gte, "Unable to commit transaction", module); + } + } + } + if (okay) { + request.setAttribute("_EVENT_MESSAGE_", UtilProperties.getMessage(resource, "IdealSuccessFull", locale)); + // attempt to release the offline hold on the order (workflow) + OrderChangeHelper.releaseInitialOrderHold(dispatcher, orderId); + // call the email confirm service + Map<String, String> emailContext = UtilMisc.toMap("orderId", orderId, "userLogin", userLogin); + try { + dispatcher.runSync("sendOrderConfirmation", emailContext); + } catch (GenericServiceException e) { + Debug.logError(e, "Problems sending email confirmation", module); + } + } + return "success"; + } + + private static boolean setPaymentPreferences(Delegator delegator, LocalDispatcher dispatcher, GenericValue userLogin, String orderId, HttpServletRequest request) { + Debug.logVerbose("Setting payment prefrences..", module); + List <GenericValue> paymentPrefs = null; + try { + Map <String, String> paymentFields = UtilMisc.toMap("orderId", orderId, "statusId", "PAYMENT_NOT_RECEIVED"); + paymentPrefs = delegator.findByAnd("OrderPaymentPreference", paymentFields); + } catch (GenericEntityException e) { + Debug.logError(e, "Cannot get payment preferences for order #" + orderId, module); + return false; + } + if (paymentPrefs.size() > 0) { + Iterator <GenericValue> i = paymentPrefs.iterator(); + while (i.hasNext()) { + GenericValue pref = i.next(); + boolean okay = setPaymentPreference(dispatcher, userLogin, pref, request); + if (!okay) + return false; + } + } + return true; + } + + private static boolean setPaymentPreference(LocalDispatcher dispatcher, GenericValue userLogin, GenericValue paymentPreference, HttpServletRequest request) { + Locale locale = UtilHttp.getLocale(request); + String paymentAmount = (String) request.getAttribute("paymentAmount"); + String paymentStatus = (String) request.getAttribute("paymentStatus"); + String transactionId = (String) request.getAttribute("transactionId"); + + List <GenericValue> toStore = new LinkedList <GenericValue> (); + java.sql.Timestamp authDate = UtilDateTime.nowTimestamp(); + + paymentPreference.set("maxAmount", new BigDecimal(paymentAmount)); + if ("Success".equals(paymentStatus)) { + paymentPreference.set("statusId", "PAYMENT_RECEIVED"); + } else if ("Cancelled".equals(paymentStatus)) { + paymentPreference.set("statusId", "PAYMENT_CANCELLED"); + } else { + paymentPreference.set("statusId", "PAYMENT_NOT_RECEIVED"); + } + toStore.add(paymentPreference); + Delegator delegator = paymentPreference.getDelegator(); + + // create the PaymentGatewayResponse + String responseId = delegator.getNextSeqId("PaymentGatewayResponse"); + GenericValue response = delegator.makeValue("PaymentGatewayResponse"); + response.set("paymentGatewayResponseId", responseId); + response.set("paymentServiceTypeEnumId", "PRDS_PAY_EXTERNAL"); + response.set("orderPaymentPreferenceId", paymentPreference.get("orderPaymentPreferenceId")); + response.set("paymentMethodTypeId", paymentPreference.get("paymentMethodTypeId")); + response.set("paymentMethodId", paymentPreference.get("paymentMethodId")); + + // set the auth info + response.set("amount", new BigDecimal(paymentAmount)); + response.set("currencyUomId", "EUR"); + response.set("referenceNum", transactionId); + response.set("gatewayCode", paymentStatus); + response.set("gatewayFlag", paymentStatus.substring(0,1)); + response.set("transactionDate", authDate); + toStore.add(response); + + try { + delegator.storeAll(toStore); + } catch (GenericEntityException e) { + Debug.logError(e, "Cannot set payment preference/payment info", module); + return false; + } + + GenericValue userLoginId = null; + try { + userLoginId = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", "system"), false); + } catch (GenericEntityException e) { + return false; + } + + // create a payment record too + Map <String, Object> results = null; + try { + String comment = UtilProperties.getMessage(resource, "AccountingPaymentReceiveViaiDEAL", locale); + results = dispatcher.runSync("createPaymentFromPreference", UtilMisc.toMap("userLogin", userLoginId, + "orderPaymentPreferenceId", paymentPreference.get("orderPaymentPreferenceId"), "comments", comment)); + } catch (GenericServiceException e) { + Debug.logError(e, "Failed to execute service createPaymentFromPreference", module); + request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.failedToExecuteServiceCreatePaymentFromPreference", locale)); + return false; + } + + if ((results == null) || (results.get(ModelService.RESPONSE_MESSAGE).equals(ModelService.RESPOND_ERROR))) { + Debug.logError((String) results.get(ModelService.ERROR_MESSAGE), module); + request.setAttribute("_ERROR_MESSAGE_", results.get(ModelService.ERROR_MESSAGE)); + return false; + } + + return true; + } + + private static String getPaymentGatewayConfigValue(Delegator delegator, String paymentGatewayConfigId, String paymentGatewayConfigParameterName, + String resource, String parameterName) { + String returnValue = ""; + if (UtilValidate.isNotEmpty(paymentGatewayConfigId)) { + try { + GenericValue ideal = delegator.findOne("PaymentGatewayiDEAL", UtilMisc.toMap("paymentGatewayConfigId", paymentGatewayConfigId), false); + if (UtilValidate.isNotEmpty(ideal)) { + Object idealField = ideal.get(paymentGatewayConfigParameterName); + if (idealField != null) { + returnValue = idealField.toString().trim(); + } + } + } catch (GenericEntityException e) { + Debug.logError(e, module); + } + } else { + String value = UtilProperties.getPropertyValue(resource, parameterName); + if (value != null) { + returnValue = value.trim(); + } + } + return returnValue; + } + + public static List<Issuer> getIssuerList() { + List<Issuer> issuerList = FastList.newInstance(); + try { + IdealConnector connector = new IdealConnector("payment"); + Issuers issuers = connector.getIssuerList(); + List<Issuer> shortList = issuers.getShortList(); + List<Issuer> longList = issuers.getLongList(); + for (Iterator<Issuer> iter = shortList.iterator(); iter.hasNext();) { + Issuer issuer = (Issuer) iter.next(); + issuerList.add(issuer); + } + for (Iterator<Issuer> iter = longList.iterator(); iter.hasNext();) { + Issuer issuer = (Issuer) iter.next(); + issuerList.add(issuer); + } + } catch (IdealException ex){ + Debug.logError(ex.getMessage(), module); + } + + return issuerList; + } +} Added: ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/IdealPaymentServiceTest.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/IdealPaymentServiceTest.java?rev=1062608&view=auto ============================================================================== --- ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/IdealPaymentServiceTest.java (added) +++ ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/IdealPaymentServiceTest.java Mon Jan 24 02:27:11 2011 @@ -0,0 +1,230 @@ +/******************************************************************************* + * 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.ideal; + + +import java.sql.Timestamp; +import java.util.Random; + +import junit.framework.TestCase; +import org.ofbiz.base.util.Debug; +import org.ofbiz.base.util.UtilDateTime; +import org.ofbiz.service.testtools.OFBizTestCase; +import com.ing.ideal.connector.IdealConnector; +import com.ing.ideal.connector.IdealException; +import com.ing.ideal.connector.Transaction; + + +public class IdealPaymentServiceTest extends OFBizTestCase{ + + public IdealPaymentServiceTest(String name) { + super(name); + } + + public static final String module = IdealPaymentServiceTest.class.getName(); + + // test data + protected String orderId = null; + protected String orderDiscription = null; + protected String issuerId = null; + protected String merchantReturnURL = null; + protected String configFile = null; + + @Override + protected void setUp() throws Exception { + // populate test data + configFile = "paymentTest"; + orderId = "testOrder1000"; + issuerId = "0151"; + orderDiscription = "Test Order Description"; + merchantReturnURL = "http://localhost:8080/ecommerce"; + } + + public void testDirectoryRequest() throws Exception{ + try { + IdealConnector connector = new IdealConnector(configFile); + connector.getIssuerList(); + } catch (IdealException ex){ + TestCase.fail(ex.getMessage()); + } + } + + public void testOrderSuccuess() throws Exception{ + try { + IdealConnector connector = new IdealConnector(configFile); + int amount = 1; + int amountFormat = amount * 100; + + Transaction transaction = new Transaction(); + transaction.setIssuerID(issuerId); + transaction.setAmount(Integer.toString(amountFormat)); + transaction.setPurchaseID(orderId); + transaction.setDescription(orderDiscription); + + Random random = new Random(); + String EntranceCode = Long.toString(Math.abs(random.nextLong()), 36); + transaction.setEntranceCode(EntranceCode); + transaction.setMerchantReturnURL(merchantReturnURL); + Transaction trx = connector.requestTransaction(transaction); + String transactionId = trx.getTransactionID(); + Transaction transactionCustomer = connector.requestTransactionStatus(transactionId); + transactionCustomer.isSuccess(); + Debug.logInfo("[testOrderSuccuess] IssuerID Messages from iDEAL: " + transactionCustomer.getIssuerID(), module); + Debug.logInfo("[testOrderSuccuess] Status Messages from iDEAL: " + transactionCustomer.getStatus(), module); + } catch (IdealException ex) { + TestCase.fail(ex.getMessage()); + } + } + + public void testOrderCancelled() throws Exception{ + try { + IdealConnector connector = new IdealConnector(configFile); + int amount = 2; + int amountFormat = amount * 100; + + Transaction transaction = new Transaction(); + transaction.setIssuerID(issuerId); + transaction.setAmount(Integer.toString(amountFormat)); + transaction.setPurchaseID(orderId); + transaction.setDescription(orderDiscription); + + Random random = new Random(); + String EntranceCode = Long.toString(Math.abs(random.nextLong()), 36); + transaction.setEntranceCode(EntranceCode); + transaction.setMerchantReturnURL(merchantReturnURL); + Transaction trx = connector.requestTransaction(transaction); + String transactionId = trx.getTransactionID(); + Transaction transactionCustomer = connector.requestTransactionStatus(transactionId); + transactionCustomer.isCancelled(); + Debug.logInfo("[testOrderCancelled] IssuerID Messages from iDEAL: " + transactionCustomer.getIssuerID(), module); + Debug.logInfo("[testOrderCancelled] Status Messages from iDEAL: " + transactionCustomer.getStatus(), module); + } catch (IdealException ex) { + TestCase.fail(ex.getMessage()); + } + } + + public void testOrderExpired() throws Exception{ + try { + IdealConnector connector = new IdealConnector(configFile); + int amount = 3; + int amountFormat = amount * 100; + + Transaction transaction = new Transaction(); + transaction.setIssuerID(issuerId); + transaction.setAmount(Integer.toString(amountFormat)); + transaction.setPurchaseID(orderId); + transaction.setDescription(orderDiscription); + + Random random = new Random(); + String EntranceCode = Long.toString(Math.abs(random.nextLong()), 36); + transaction.setEntranceCode(EntranceCode); + transaction.setMerchantReturnURL(merchantReturnURL); + Transaction trx = connector.requestTransaction(transaction); + String transactionId = trx.getTransactionID(); + Transaction transactionCustomer = connector.requestTransactionStatus(transactionId); + transactionCustomer.isExpired(); + Debug.logInfo("[testOrderExpired] IssuerID Messages from iDEAL: " + transactionCustomer.getIssuerID(), module); + Debug.logInfo("[testOrderExpired] Status Messages from iDEAL: " + transactionCustomer.getStatus(), module); + } catch (IdealException ex) { + TestCase.fail(ex.getMessage()); + } + } + + public void testOrderOpen() throws Exception{ + try { + IdealConnector connector = new IdealConnector(configFile); + int amount = 4; + int amountFormat = amount * 100; + + Transaction transaction = new Transaction(); + transaction.setIssuerID(issuerId); + transaction.setAmount(Integer.toString(amountFormat)); + transaction.setPurchaseID(orderId); + transaction.setDescription(orderDiscription); + + Random random = new Random(); + String EntranceCode = Long.toString(Math.abs(random.nextLong()), 36); + transaction.setEntranceCode(EntranceCode); + transaction.setMerchantReturnURL(merchantReturnURL); + Transaction trx = connector.requestTransaction(transaction); + String transactionId = trx.getTransactionID(); + Transaction transactionCustomer = connector.requestTransactionStatus(transactionId); + transactionCustomer.isOpen(); + Debug.logInfo("[testOrderOpen] IssuerID Messages from iDEAL: " + transactionCustomer.getIssuerID(), module); + Debug.logInfo("[testOrderOpen] Status Messages from iDEAL: " + transactionCustomer.getStatus(), module); + } catch (IdealException ex) { + TestCase.fail(ex.getMessage()); + } + } + + public void testOrderFailure() throws Exception{ + try { + IdealConnector connector = new IdealConnector(configFile); + int amount = 5; + int amountFormat = amount * 100; + + Transaction transaction = new Transaction(); + transaction.setIssuerID(issuerId); + transaction.setAmount(Integer.toString(amountFormat)); + transaction.setPurchaseID(orderId); + transaction.setDescription(orderDiscription); + + Random random = new Random(); + String EntranceCode = Long.toString(Math.abs(random.nextLong()), 36); + transaction.setEntranceCode(EntranceCode); + transaction.setMerchantReturnURL(merchantReturnURL); + Transaction trx = connector.requestTransaction(transaction); + String transactionId = trx.getTransactionID(); + Transaction transactionCustomer = connector.requestTransactionStatus(transactionId); + transactionCustomer.isFailure(); + Debug.logInfo("[testOrderFailure] IssuerID Messages from iDEAL: " + transactionCustomer.getIssuerID(), module); + Debug.logInfo("[testOrderFailure] Status Messages from iDEAL: " + transactionCustomer.getStatus(), module); + } catch (IdealException ex) { + TestCase.fail(ex.getMessage()); + } + } + + public void testOrderError() throws Exception{ + try { + IdealConnector connector = new IdealConnector(configFile); + int amount = 7; + int amountFormat = amount * 100; + + Transaction transaction = new Transaction(); + transaction.setIssuerID(issuerId); + transaction.setAmount(Integer.toString(amountFormat)); + transaction.setPurchaseID(orderId); + transaction.setDescription(orderDiscription); + + Random random = new Random(); + String EntranceCode = Long.toString(Math.abs(random.nextLong()), 36); + transaction.setEntranceCode(EntranceCode); + transaction.setMerchantReturnURL(merchantReturnURL); + IdealException ex = new IdealException(""); + ex.setErrorCode("SO1000"); + Transaction transactionCustomer = connector.requestTransaction(transaction); + Debug.logInfo("[testOrderError] IssuerID Messages from iDEAL: " + transactionCustomer.getIssuerID(), module); + Debug.logInfo("[testOrderError] Status Messages from iDEAL: " + transactionCustomer.getStatus(), module); + } catch (IdealException ex){ + TestCase.fail(ex.getMessage()); + } + } +} Added: ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/readme URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/readme?rev=1062608&view=auto ============================================================================== --- ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/readme (added) +++ ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/ideal/readme Mon Jan 24 02:27:11 2011 @@ -0,0 +1,54 @@ +### How to Test ### +1. go to ecommerce website. +2. select product and add to cart. +3. at 3)How shall you pay?, Pay With iDEAL which show the consumerâs bank. +4. submit order. + +### config ### +first of all, add the following jars to the /applications/accounting/lib directory: +ing-iac-2.0.3.jar +jibx-run.jar + +1. go to Accounting component +2. go to Payment Gateway Config, then click find +3. select iDEAL Payment Gateway (iDEAL Config) +4. fill in Update Payment Gateway Config iDEAL (Merchant Id, Merchant ReturnURL, etc.), then click Update + + +### Configuration Attributes for detailed information for activate ### +1. merchantID: The ID of the webshop, received by the acceptor during the registration process + +2. merchantSubId: SubID of the webshop, default value = 0 (zero); only to be changed in consultation with the acquirer + +3. merchantReturnURL: URL of the page in the webshop to which the consumer is redirected after an iDEAL transaction. This value can be overruled as necessary in the webshop implementation. + +4. acquirerURL: URL of the acceptorâs acquirer; the following prescribed values apply to ING: + ⢠Test environment: https://idealtest.secure-ing.com/ideal/iDeal + ⢠Production environment: https://ideal.secure-ing.com/ideal/iDeal +5. acquirerTimeout: Number of seconds (default = 10) of waiting time for a response from the iDEAL services. If no response is received during that time, an exception is displayed. + +6. privateCert: Name of the acceptorâs organization as given during the creation of his or her own certificate. See section 0 for more information about the acceptorâs certificate. + +7. acquirerKeyStoreFilename / acquirerKeyStorePassword: Keystore file and acquirerâs password + +8. merchantKeyStoreFilename / merchantKeyStorePassword: Keystore file and merchantâs password + + +### Example iDEAL Configuration:### +You can config on payment.properties + +merchantId=005040237 +merchantSubId=0 +merchantReturnURL=http://localhost:8080/ecommerce/control/idealNotify +acquirerURL=https://idealtest.secure-ing.com/ideal/iDeal +acquirerTimeout=10 +expirationPeriod=PT1H +privateCert=acquirer.keystore +merchantKeyStoreFilename=merchant.keystore +merchantKeyStorePassword={xor}bm1sa2pp +acquirerKeyStoreFilename=acquirer.keystore +acquirerKeyStorePassword={xor}MiYPPiwsKDAtOw== + + + + Modified: ofbiz/trunk/applications/accounting/testdef/paymenttests.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/testdef/paymenttests.xml?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/accounting/testdef/paymenttests.xml (original) +++ ofbiz/trunk/applications/accounting/testdef/paymenttests.xml Mon Jan 24 02:27:11 2011 @@ -31,4 +31,9 @@ <junit-test-suite class-name="org.ofbiz.accounting.thirdparty.securepay.SecurePayServiceTest"/> </test-case--> + <!-- enable when you get acquirer.keystore, merchant.crt, merchant.keystore from sandbox and copy to /applications/accounting/config and configured --> + <!-- <test-case case-name="ideal-payment-tests"> + <junit-test-suite class-name="org.ofbiz.accounting.thirdparty.ideal.IdealPaymentServiceTest"/> + </test-case>--> + </test-suite> Modified: ofbiz/trunk/applications/accounting/webapp/accounting/WEB-INF/controller.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/webapp/accounting/WEB-INF/controller.xml?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/accounting/webapp/accounting/WEB-INF/controller.xml (original) +++ ofbiz/trunk/applications/accounting/webapp/accounting/WEB-INF/controller.xml Mon Jan 24 02:27:11 2011 @@ -572,6 +572,12 @@ under the License. <response name="success" type="view" value="EditPaymentGatewayConfig"/> <response name="error" type="view" value="EditPaymentGatewayConfig"/> </request-map> + <request-map uri="UpdatePaymentGatewayConfigiDEAL"> + <security https="true" auth="true"/> + <event type="service" invoke="updatePaymentGatewayConfigiDEAL"/> + <response name="success" type="view" value="EditPaymentGatewayConfig"/> + <response name="error" type="view" value="EditPaymentGatewayConfig"/> + </request-map> <!-- TO BE REMOVED <request-map uri="TransactionReports"> Modified: ofbiz/trunk/applications/accounting/widget/PaymentGatewayConfigForms.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/widget/PaymentGatewayConfigForms.xml?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/accounting/widget/PaymentGatewayConfigForms.xml (original) +++ ofbiz/trunk/applications/accounting/widget/PaymentGatewayConfigForms.xml Mon Jan 24 02:27:11 2011 @@ -471,4 +471,12 @@ under the License. <submit button-type="button"/> </field> </form> + + <form name="EditPaymentGatewayConfigiDEAL" type="single" target="UpdatePaymentGatewayConfigiDEAL" default-map-name="paymentGatewayiDEAL" header-row-style="header-row" default-table-style="basic-table"> + <auto-fields-entity entity-name="PaymentGatewayiDEAL" default-field-type="edit"/> + <field name="paymentGatewayConfigId"><hidden/></field> + <field name="submitButton" title="${uiLabelMap.CommonUpdate}" widget-style="smallSubmit"> + <submit button-type="button"/> + </field> + </form> </forms> Modified: ofbiz/trunk/applications/accounting/widget/PaymentGatewayConfigScreens.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/widget/PaymentGatewayConfigScreens.xml?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/accounting/widget/PaymentGatewayConfigScreens.xml (original) +++ ofbiz/trunk/applications/accounting/widget/PaymentGatewayConfigScreens.xml Mon Jan 24 02:27:11 2011 @@ -113,6 +113,9 @@ under the License. <entity-one entity-name="PaymentGatewaySecurePay" value-field="paymentGatewaySecurePay"> <field-map field-name="paymentGatewayConfigId" from-field="parameters.paymentGatewayConfigId"/> </entity-one> + <entity-one entity-name="PaymentGatewayiDEAL" value-field="paymentGatewayiDEAL"> + <field-map field-name="paymentGatewayConfigId" from-field="parameters.paymentGatewayConfigId"/> + </entity-one> </actions> <widgets> <decorator-screen name="GenericPaymentGatewayConfigDecorator"> @@ -221,6 +224,16 @@ under the License. </screenlet> </widgets> </section> + <section> + <condition> + <not><if-empty field="paymentGatewayiDEAL"/></not> + </condition> + <widgets> + <screenlet title="${uiLabelMap.PageTitleUpdatePaymentGatewayConfigiDEAL}"> + <include-form name="EditPaymentGatewayConfigiDEAL" location="component://accounting/widget/PaymentGatewayConfigForms.xml"/> + </screenlet> + </widgets> + </section> </decorator-section> </decorator-screen> </widgets> Modified: ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutEvents.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutEvents.java?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutEvents.java (original) +++ ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutEvents.java Mon Jan 24 02:27:11 2011 @@ -294,6 +294,11 @@ public class CheckOutEvents { //Locale locale = UtilHttp.getLocale(request); Map selectedPaymentMethods = new HashMap(); String[] paymentMethods = request.getParameterValues("checkOutPaymentId"); + + if (UtilValidate.isNotEmpty(request.getParameter("issuerId"))) { + request.setAttribute("issuerId", request.getParameter("issuerId")); + } + String errMsg = null; if (paymentMethods != null) { @@ -456,6 +461,12 @@ public class CheckOutEvents { request.setAttribute("orderAdditionalEmails", cart.getOrderAdditionalEmails()); } } + + String issuerId = request.getParameter("issuerId"); + if (UtilValidate.isNotEmpty(issuerId)) { + request.setAttribute("issuerId", issuerId); + } + return cart.getOrderType().toLowerCase(); } Modified: ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/CheckoutPayment.groovy URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/CheckoutPayment.groovy?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/CheckoutPayment.groovy (original) +++ ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/CheckoutPayment.groovy Mon Jan 24 02:27:11 2011 @@ -23,6 +23,7 @@ import org.ofbiz.entity.util.*; import org.ofbiz.accounting.payment.*; import org.ofbiz.party.contact.*; import org.ofbiz.product.store.*; +import org.ofbiz.accounting.thirdparty.ideal.IdealEvents; cart = session.getAttribute("shoppingCart"); currencyUomId = cart.getCurrency(); @@ -56,3 +57,8 @@ if (billingAccountList) { context.selectedBillingAccountId = cart.getBillingAccountId(); context.billingAccountList = billingAccountList; } + +issuerList = IdealEvents.getIssuerList(); +if (issuerList) { + context.issuerList = issuerList; +} Modified: ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/controller.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/controller.xml?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/controller.xml (original) +++ ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/WEB-INF/controller.xml Mon Jan 24 02:27:11 2011 @@ -756,6 +756,7 @@ under the License. <response name="paypal" type="request" value="callPayPal"/> <response name="billact" type="request" value="emailorder"/> <response name="cod" type="request" value="emailorder"/> + <response name="ideal" type="request" value="callIdeal"/> <response name="error" type="view" value="checkoutreview"/> </request-map> @@ -797,6 +798,18 @@ under the License. <response name="success" type="view" value="main"/> <response name="error" type="view" value="main"/> </request-map> + <request-map uri="callIdeal"> + <security https="true" direct-request="false"/> + <event type="java" path="org.ofbiz.accounting.thirdparty.ideal.IdealEvents" invoke="callIdeal"/> + <response name="success" type="none"/> + <response name="error" type="view" value="checkoutreview"/> + </request-map> + <request-map uri="idealNotify"> + <security https="false"/> + <event type="java" path="org.ofbiz.accounting.thirdparty.ideal.IdealEvents" invoke="idealNotify"/> + <response name="success" type="view" value="ordercomplete"/> + <response name="error" type="view" value="checkoutreview"/> + </request-map> <!-- PayPal Express Checkout Requests --> <request-map uri="setPayPalCheckout"> Modified: ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/order/checkoutpayment.ftl URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/order/checkoutpayment.ftl?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/order/checkoutpayment.ftl (original) +++ ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/order/checkoutpayment.ftl Mon Jan 24 02:27:11 2011 @@ -56,14 +56,41 @@ function submitForm(form, mode, value) { form.submit(); } //]]> +$(document).ready(function(){ +var issuerId = ""; + if ($('#checkOutPaymentId_IDEAL').attr('checked') == true) { + $('#issuers').show(); + issuerId = $('#issuer').val(); + $('#issuerId').val(issuerId); + } else { + $('#issuers').hide(); + $('#issuerId').val(''); + } + $('input:radio').click(function(){ + if ($(this).val() == "EXT_IDEAL") { + $('#issuers').show(); + issuerId = $('#issuer').val(); + $('#issuerId').val(issuerId); + } else { + $('#issuers').hide(); + $('#issuerId').val(''); + } + }); + $('#issuer').change(function(){ + issuerId = $(this).val(); + $('#issuerId').val(issuerId); + }); +}); </script> + <#assign cart = shoppingCart?if_exists /> <form method="post" id="checkoutInfoForm" action=""> <fieldset> <input type="hidden" name="checkoutpage" value="payment" /> <input type="hidden" name="BACK_PAGE" value="checkoutoptions" /> + <input type="hidden" name="issuerId" id="issuerId" value="" /> <div class="screenlet"> <div class="screenlet-title-bar"> @@ -104,6 +131,23 @@ function submitForm(form, mode, value) { <label for="checkOutPaymentId_PAYPAL">${uiLabelMap.AccountingPayWithPayPal}</label> </div> </#if> + <#if productStorePaymentMethodTypeIdMap.EXT_IDEAL?exists> + <div> + <input type="radio" id="checkOutPaymentId_IDEAL" name="checkOutPaymentId" value="EXT_IDEAL" <#if "EXT_IDEAL" == checkOutPaymentId>checked="checked"</#if> /> + <label for="checkOutPaymentId_IDEAL">${uiLabelMap.AccountingPayWithiDEAL}</label> + </div> + + <div id="issuers"> + <div><label >${uiLabelMap.AccountingBank}</label></div> + <select name="issuer" id="issuer"> + <#if issuerList?has_content> + <#list issuerList as issuer> + <option value="${issuer.getIssuerID()}" >${issuer.getIssuerName()}</option> + </#list> + </#if> + </select> + </div> + </#if> <#if !paymentMethodList?has_content> <div> <strong>${uiLabelMap.AccountingNoPaymentMethods}.</strong> Modified: ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/order/checkoutreview.ftl URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/order/checkoutreview.ftl?rev=1062608&r1=1062607&r2=1062608&view=diff ============================================================================== --- ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/order/checkoutreview.ftl (original) +++ ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/order/checkoutreview.ftl Mon Jan 24 02:27:11 2011 @@ -51,6 +51,9 @@ under the License. <#if (requestParameters.checkoutpage)?has_content> <input type="hidden" name="checkoutpage" value="${requestParameters.checkoutpage}" /> </#if> + <#if (requestAttributes.issuerId)?has_content> + <input type="hidden" name="issuerId" value="${requestAttributes.issuerId}" /> + </#if> <input type="button" name="processButton" value="${uiLabelMap.OrderSubmitOrder}" onclick="processOrder();" class="mediumSubmit" /> </form> <#-- doesn't work with Safari, seems to work with IE, Mozilla <a href="#" onclick="processOrder();" class="buttontextbig">[${uiLabelMap.OrderSubmitOrder}] </a> --> |
Free forum by Nabble | Edit this page |