Mostrando postagens com marcador E-Commerce. Mostrar todas as postagens
Mostrando postagens com marcador E-Commerce. Mostrar todas as postagens

quarta-feira, 7 de março de 2012

O Barato sai Caro

Quase 30 mil blogs do WordPress foram infectados em uma nova onda de ataques orquestrada por uma gangue de cibercriminosos para distribuir antivírus falsos. O alerta é de pesquisadores da empresa de segurança Websense.

Os ataques resultaram em mais de 200 mil páginas infectadas que redirecionam os usuários para sites que mostram verificações falsas de antivírus. Isso faz parte de uma campanha de distribuição de AVs falsos que vem acontecendo há meses, disseram os pesquisadores.

Falsas verificações de antivírus não são novidade. Na verdade, há alguns anos atrás este tipo de engenharia social foi um dos principais métodos de distribuição de scareware aos internautas.

No entanto, muitas gangues de cibercriminosos, desde então, começaram a se focar em ataques de download automático (drive-by) que exploram vulnerabilidades do navegador e de plug-ins para fazer o download automático e instalar malware.

O grande número de páginas infectadas nesta campanha é uma indicação de que esses golpes continuam funcionando, disse Elad Sharf, pesquisador sênior de segurança da Websense Labs. "Sites vulneráveis ​​são uma fonte rica de oportunidades para os criminosos."

Mais de 85% dos sites comprometidos são dos EUA, mas os visitantes estão no mundo todo. "O ataque pode ser específico para os EUA, mas todo mundo está em risco quando visitar estas páginas comprometidas", disse Sharf.

Muitos dos blogs comprometidos nestes ataques recentes rodam versões desatualizadas do WordPress, tinham plug-ins vulneráveis instalados ou senhas administrativas suscetíveis a ataques de força bruta, disse David Dede, um pesquisador de segurança da Sucuri Security. "Parece que os crackers estão tentando de tudo ultimamente."

Pesquisadores da Sucuri também têm acompanhado essa campanha de distribuição de scareware e descobriram que um plug-in para WP chamado ToolsPack foi instalado em muitos dos blogs comprometidos. Este plug-in se disfarça como uma coleção de ferramentas de administração do WP, mas na realidade contém um backdoor que os atacantes usam para manter o acesso não autorizado aos locais afetados, disse Dede.

Não tenho nada contra as tecnologias open source, porém o fato de muitas empresas estarem usando esses produtos como plataformas reais é realmente preocupante. O Open Source se destina a estudos de tecnologias e suas aplicações, na maioria dos casos são betas que vão se atualizando ao longo dos anos.

Empresas que veem esses produtos prontos como fonte de renda colocam em risco o cliente e seus afiliados os sugeitando a perda de dados, malwares e viros de todos os tipos.

Isso fica facil para a pessoa mal intenciona uma vez que ela já tem o código fonte e pode explorar todas as falhas conhecidas, é mais uma questão de tentativa e erro do que talento tecnológico.

sexta-feira, 3 de junho de 2011

Carrinho de Compras - Parte 2.1 (Integração com PagSeguro do UOL - Retorno Automático)

Como eu tinha prometido vamos continuar com a série "Carrinho de Compras", quem não viu o primeiro post Carrinho de Compras - Parte 1 e Parte 2 recomendo dar uma olhada apenas para ter uma idéiade como nosso carrinho funciona e em que ponto estamos.

Ontem finalizamos o envio de dados para o PagSeguro do UOL e hoje (que rufem os tambores), vamos falar do Retorno Automático do PagSeguro.

Para isso, precisamos primeiro saber como ele funciona e definir nossa URL DE RETORNO e o TOKEN. Esse procedimento, tenta evitar dores de cabeça de pessoas comprando sem estar na sua loja. Como vimos ontem, o pagseguro, só pede um form com submit sem nenhum tipo de validação.

A validação acontece, quando o PagSeguro gera a "pergunta", que no caso chamamos de Retorno Automático. Uma observação, nesse caso seus testes devem ser online, pois vamos usar a session da sua aplicação para verificar e validar dos dados a serem confirmados com a URL de Retorno.

Para este processo vamos criar um novo componente e vamos chama-lo de PagSeguroRetorno.cfc. Este compoennte será usado na nossa página de retorno, e irá disparar ações de confirmação dos dados da compra.

PagSeguroRetorno.cfc
   1: <cfset Variable.COMMAND = "validar">
   2: <cfset Variables.VALIDATOR_URL = "https://pagseguro.uol.com.br/pagseguro-ws/checkout/NPI.jhtml">
   3: <cfset Variables.TOKEN = "SEU_TOKEN" />
   4: <cfset Variables.dsEmail = "EMAIL_CADASTRADO_PAGSEGURO" />
   5: <cfset Variables.result = structNew()>
Iniciamos o processo com nossas váriaveis que serão manipuladas pelo componente.

setReturn
   1: <cffunction name="setReturn" access="public" returntype="void" output="false">
   2:     <cfargument name="data" type="struct" required="true">
   3:     <cfset var arrForm = listToArray(arguments.data.FieldNames)>
   4:     <cfloop array="#arrForm#" index="currentItem">
   5:         <cfset Variables.result["#currentItem#"] = arguments.data[currentItem]>
   6:     </cfloop>
   7: </cffunction>
Criamos um método setReturn, que será responsável por receber o retorno do PagSeguro e manipular este resultado de acordo com nossa necessidade. Nesse momento, apenas nos preocupamos com guardar a informação. Para evitar um monte de linhas, realizamos um loop sobre a estrutura de dados recebida, guardando os dados na estrutura result.

confirm
   1: <cffunction name="confirm" access="public" returntype="void" output="false">
   2:     <cfhttp url="#VALIDATOR_URL#" method="get" resolveurl="false" charset="iso-8859-1">
   3:         <cfhttpparam name="Comando" type="url" value="#Variables.COMMAND#">
   4:         <cfhttpparam name="Token" type="url" value="#Variables.TOKEN#">
   5:         
   6:         <cfloop collection="variables.result" item="currentItem">
   7:             <cfhttpparam name="#currentItem#" type="url" value="#variables.result[currentItem]#">
   8:         </cfloop>
   9:     </cfhttp>
  10:     <cfswitch expression="#trim(cfhttp.FileContent)#">
  11:         <cfcase value="VERIFICADO">
  12:         <!--- Verifique se a TransacaoID não foi previamente processada --->
  13:         <!--- Verifique se o email recebido (VendedorEmail) é o seu email --->
  14:         <!--- Verifique se o valor do pagamento está correto --->
  15:         <!--- Processe o pagamento salvando os dados em seu banco de dados --->
  16:             <cfset FileWrite("#getDirectoryFromPath(expandPath('*.*'))#FORM_TRUE#DateFormat(Now(), 'yyyy-mm-dd-hh-mm-ss')#.htm", value)>
  17:         </cfcase>
  18:         <cfcase value="FALSO">
  19:             <!--- A Requisição não foi confirmada pelo PagSeguro e pode ser uma compra falsa --->
  20:             <cfset FileWrite("#getDirectoryFromPath(expandPath('*.*'))#FORM_FALSE#DateFormat(Now(), 'yyyy-mm-dd-hh-mm-ss')#.htm", value)>
  21:         </cfcase>
  22:     </cfswitch>
  23: </cffunction>
Finalmente, de posse dos dados, realizamos a confirmação. Para isso, enviamos um post com o comando Validar e nosso Token, junto com os dados da compra.

Lembrando que aqui estamos tratando de um exemplo, no mundo real, antes de informar a validação, verificamos o id da nossa transação no e-commerce e se o carrinho é igual ao que temos no site, para só então verificarmos se os dados conferem com a informação do PagSeguro, guardando as informações adicionais.

retornoPagSeguro.cfm
   1: <cfif structKeyExists(Form, "FieldNames")>
   2:     <cfset objPagSeguroReturn = createObject("component", "PagSeguroRetorno")>
   3:     <cfset objPagSeguroReturn.setReturn(form)>
   4:     <cfset objPagSeguroReturn.confirm()>
   5: </cfif>
Este código, deve ir na sua página de retorno, a mesma que você informou para o PagSeguro. Nesse momento, verificamos se recebemos algum retorno de POST e em seguida, iniciamos nosso componente PagSeguroRetorno.cfc informando o retorno que recebemos e confirmando a transação.

Bom é isso, espero ter ajudado alguém com este tutorial e agora só volto na próxima quarta-feira, falando da integração com Pagamento Digital do Buscapé.

E finalmente, para quem cansou de ler, esta tudo pronto para download no link http://www.flagnet.inf.br/downloads/shoppingCart-part2.1.rar

quinta-feira, 2 de junho de 2011

Carrinho de Compras - Parte 2 (Integração com PagSeguro do UOL)

Como eu tinha prometido vamos continuar com a série "Carrinho de Compras", quem não viu o primeiro post Carrinho de Compras - Parte 1, recomendo dar uma olhada apenas para ter uma idéiade como nosso carrinho funciona.

Hoje a idéia é falar da integração com o PagSeguro do UOL através do nosso ColdFusion. O primeiro desafio é documentação em ColdFusion, que por ser uma linguagem extremamente fácil e produtiva, as pessoas acabam esquecendo de criar documentação, meu objetivo é mudar isso radicalmente.

Para a integração, vamos precisar de dois manuais no site do PagSeguro. O primeiro é o da integração com Carrinho Próprio e o segundo que é o Retorno Automático de Dados

Apenas lembrando que a mágica depende da configuração correta na sua conta PagSeguro, se você ainda não o fez ou quer revizar vamos aos passos:

  1. Criar uma conta no PagSeguro
  2. Se for usar a conta em produção, é bom validar os dados.
  3. Lembre-se de configurar o Frete, no menu Preferências/Frete
  4. Defina o link para o Retorno Automático de Dados, e gere o Token no menu Preferências/Retorno automático de dados
 Após esses passos simples, vamos a parte código da nossa integração. Na página de integração com o carrinho, é explicado que você tem duas opções para o envio de dados do comprador. Uma você deixa isso a cargo do PagSeguro, e outra você realiza este envio.

Para este post vamos fazer o modelo de enviarmos todos os dados, até porque você provavelmente nesse ponto, já esta com o usuário logado no seu e-commerce e cadastrado. Lembre-se, esse é o momento de finalização da compra, então você já deve verificar seu estoque e estar com tudo pronto.

Para facilitar nossa vida, vamos criar um novo componente chamado PagSeguro.cfc, que espero que ajude na integração da maioria dos projetos. Os métodos que percebi são:
  • setCart: vai ser o método responsável por receber os dados a serem enviados ao PagSeguro;
  • setType: para informar o tipo do carrinho, seja próprio, ou PagSeguro
  • setCoin: serve para informar o tipo de moeda, hoje o pagSeguro só trabalha com Real
  • setExtras: será utilizado para valores adicionais ou descontos
  • setClient: irá servir para informar os dados do fulano que esta fazendo a compra
  • setShipping: informaremos o tipo de envio do produto
  • parseCurrency: esse método irá converter o valor para o padrão PagSeguro
  • send: esse método irá realizar a mágica de enviar os dados para o PagSeguro
 PagSeguro.cfc
   1: <cfset Variables.ACTION = "https://pagseguro.uol.com.br/checkout/checkout.jhtml" />
   2: <cfset Variables.dsEmail = "EMAIL_CADASTRADO_PAGSEGURO" />
   3: <cfset Variables.tpCart = "CP" />
   4: <cfset Variables.tpCoin = "BRL" />
   5: <cfset Variables.tpShipping = "UC" />
   6: <cfset Variables.vlExtras = 0 />
   7: <cfset Variables.userData = structNew()>
   8: <cfset variables.cart = ArrayNew(1) />
Ao iniciar nosso processo, criamos algumas váriaveis que serão controladas pelos nossos métodos antes do envio. Algumas delas, já definimos um valor padrão, para evitar falhas ou necessidades de formas de uso na programação.

É importante lembrar que um componente deve ser simples a ponto de não termos que "adaptar" nossa programação ao funcionamento dele.

setCart
   1: <cffunction name="setCart" access="public" returntype="void" output="false">
   2:     <cfargument name="cart" type="ShoppingCart" required="true">
   3:     <cfargument name="nmLogin" type="String" default="" required="false">
   4:  
   5:     <cfif len(trim(arguments.nmLogin)) and isValid("email", arguments.nmLogin)>
   6:         <cfset Variables.dsEmail = arguments.nmLogin />
   7:     </cfif>
   8:     <cfset variables.cart = Arguments.cart.list()>
   9: </cffunction>
Algumas observações e curiosidades para o nosso setCart. De cara algo diferente no atributo type da nossa cfargument. O tipo requerido para o nosso carrinho se chama ShoppingCart, que é o mesmo componente CFC que criamos no post anterior, isso nos facilita um pouco a vida, pois estamos manipulando algo que esta de acordo com nossa especificação inicial.

Muitos podem achar que o post sai do nada, porém antes de começar essa maratona, desenhei todo o fluxo UML para o nosso projeto. O único motivo dos arquivos estarem todos juntos é para facilitar o entendimento e ajudar vocês a executarem o projeto em seu próprio servidor local.

Na verificação do login, repare que não faço uso de isDefined ou structKeyExist, isso, porque defini o cfargument com a propriedade default="", que faz o nosso cfargument funcionar como um cfparam, cria a variável que você pediu com um valor padrão, caso ela não exista. Com isso, verificamos se a quantidade de caracteres é superior a zero e se o valor que temos em mãos é um e-mail.

A técnica do len(trim("STRING")) é baseada numa regra da lógica boleana que diz "Todo número diferente de zero verdadeiro". Cuidado com as entrelinhas, 1 e -1 são verdadeiro apenas 0 é falso.

A função isValid do ColdFusion é uma das mais legais e menos conhecidas, vale a pena dar uma olhada na documentação, para as possibilidades!

setType
   1: <cffunction name="setType" access="public" returntype="void" output="false">
   2:     <cfargument name="type" type="string" required="true">
   3:     <cfset var lValidTypes = "CP,CBR">
   4:     <cfif listContainsNoCase(lValidTypes, arguments.type)>
   5:         <cfset Variables.tpCart = arguments.type>
   6:     <cfelse>
   7:         <cfset Variables.tpCart = listFirst(lValidTypes)>
   8:     </cfif>
   9: </cffunction>
Esse método, é apenas para dar opção para quem não desejar usar o Carrinho Proprio, e não afeta em nada nosso envio.

setCoin
   1: <cffunction name="setCoin" access="public" returntype="void" output="false">
   2:     <cfargument name="coin" type="string" required="true">
   3:     <cfset var lValidTypes = "BRL">
   4:     <cfif listContainsNoCase(lValidTypes, arguments.coin)>
   5:         <cfset Variables.tpCoin = arguments.type>
   6:     <cfelse>
   7:         <cfset Variables.tpCoin = listFirst(lValidTypes)>
   8:     </cfif>
   9: </cffunction>
Este é mais um para a lista de não temos muito o que fazer, mas vai que o UOL resolver colocar pagSeguro recebendo em outras moedas, esperança é a última que morre.

setExtras
   1: <cffunction name="setExtras" access="public" returntype="void" output="false">
   2:     <cfargument name="value" type="numeric" required="true">
   3:     <cfargument name="isDiscount" type="boolean" default="false" required="false">
   4:     
   5:     <cfif arguments.isDiscount>
   6:         <cfset Variables.vlExtras = arguments.value * -1>
   7:     <cfelse>
   8:         <cfset Variables.vlExtras = arguments.value>
   9:     </cfif>
  10: </cffunction>
Esse método é para evitar problemas entre acressimos e descontos. Na documentação do PagSeguro para o campo extras eles falam "Utilize este campo para acrescentar ao pedido um valor adicional, caso necessário. Exemplo: você pode incluir o valor da embalagem de presente. Você também pode enviar um valor negativo neste campo, caso deseje oferecer um desconto ao seu cliente.".

Pensando nisso, o método recebe o valor e um boleano informando se é desconto ou não. Isso evita que você tenha que fazer a conversão de desconto

setClient
   1: <cffunction name="setClient" access="public" returntype="void" output="false">
   2:     <cfargument name="nmPerson" type="string" required="true">
   3:     <cfargument name="dsEmail" type="string" required="true">
   4:     <cfargument name="nbPostalCode" type="string" required="true">
   5:     <cfargument name="dsAddress" type="string" required="true">
   6:     <cfargument name="dsDistrict" type="string" required="true">
   7:     <cfargument name="dsCity" type="string" required="true">
   8:     <cfargument name="cdState" type="string" required="true">
   9:     <cfargument name="cdDDD" type="numeric" required="true">
  10:     <cfargument name="nbTelephone" type="string" required="true">
  11:     <cfargument name="nbAddress" type="string" required="false" default="S/N">
  12:     <cfargument name="dsComplement" type="string" required="false" default="">
  13:     <cfargument name="cdCountry" type="string" required="false" default="BRA">
  14:     
  15:     <cfset Variables.userData.nmPerson = arguments.nmPerson>
  16:     <cfset Variables.userData.dsEmail = arguments.dsEmail>
  17:     <cfset Variables.userData.nbPostalCode = arguments.nbPostalCode>
  18:     <cfset Variables.userData.dsAddress = arguments.dsAddress>
  19:     <cfset Variables.userData.dsDistrict = arguments.dsDistrict>
  20:     <cfset Variables.userData.dsCity = arguments.dsCity>
  21:     <cfset Variables.userData.cdState = arguments.cdState>
  22:     <cfset Variables.userData.cdDDD = arguments.cdDDD>
  23:     <cfset Variables.userData.nbTelephone = arguments.nbTelephone>
  24:     <cfset Variables.userData.nbAddress = arguments.nbAddress>
  25:     <cfset Variables.userData.dsComplement = arguments.dsComplement>
  26:     <cfset Variables.userData.cdCountry = arguments.cdCountry>
  27: </cffunction>
Esse método,  pode ser melhorado, e seguir o padrão de componentes, para endereço, pessoa e telefone, além de validar algumas informações como e-mail, mas nesse caso, ele só irá servir para guardar as informações que serão enviadas ao PagSeguro.

setShipping
   1: <cffunction name="setShipping" access="public" returntype="void" output="false">
   2:     <cfargument name="shipping" type="string" required="true">
   3:     <cfset var lValidTypes = "UC,EN,SD">
   4:     <cfif listContainsNoCase(lValidTypes, arguments.shipping)>
   5:         <cfset Variables.tpShipping = arguments.type>
   6:     <cfelse>
   7:         <cfset Variables.tpShipping = listFirst(lValidTypes)>
   8:     </cfif>
   9: </cffunction>
Mais um da série, não tenho nada a dizer. A única observação é o tipo "UC" que estamos criando especialmente para o nosso PagSeguro.cfc. Se o nosso tipo de envio for "UC", não informaremos o tipo, fazendo com que o PagSeguro pergunte ao usuário, como ele deseja receber.

parseCurrency
   1: <cffunction name="parseCurrency" access="private" returntype="String" output="false">
   2:     <cfargument name="value" type="numeric" required="yes">
   3:     
   4:     <cfset var strResult = LSCurrencyFormat(Arguments.value, "none")>
   5:     <cfset strResult = trim(REReplace(strResult, "[^[:digit:]]", "", "ALL"))/>
   6:     <cfreturn strResult>
   7: </cffunction>
Esse método privado pega o valor e coloca em conformidade com a especificação do PagSeguro "Valor ... sem vírgulas ou pontos. Para um produto que custa R$ 1,00 você deverá informar 100 (somente números)."

send
Por último e talvez mais importante, a nossa "fronteira final" que é o envio dos dados para após a operação termos o nosso retorno automático.

Muitos podem pensar de cara em usar o cfhttp para envio dos dados, mas no caso do pagSeguro, o objetivo é ser uma ferramenta simples a ponto do usuário que só sabe html, também possa usar. Para o mundo ColdFusion o CFHTTP soa até natural, porém em linguens como .NET, PHP e Java a coisa não é tão simples.

Por conta disso, o envio é feito por um formulário simples o que gera algumas dores de cabeça com pessoas fazendo compras sem passar pelo seu site. A solução proposta pelo pagseguro é a utilização do token, que eu recomendo trocar pelo menos uma vez por mês ou ao dia dependendo do volume da acessos do seu e-commerce. Depois se vocês desejarem, podemos fazer uma ferramenta com essa finalidade.
   1: <cffunction name="send" access="public" returntype="string" output="no">
   2:     <cfargument name="idTransaction" type="string" required="false" default="">
   3:     <cfsavecontent variable="returnVal">
   4:         <cfoutput>
   5:         <form id="frmPagSeguro" action="#Variables.action#" method="post">
   6:             <input type="hidden" name="encoding" value="#Variables.ENCODING#">
   7:             <input type="hidden" name="email_cobranca" value="#Variables.dsEmail#">
   8:             <input type="hidden" name="tipo" value="#Variables.tpCart#">
   9:             <input type="hidden" name="moeda" value="#Variables.tpCoin#">
  10:             
  11:             <cfif len(trim(arguments.idTransaction))><input type="hidden" name="ref_transacao" value="#arguments.idTransaction#"></cfif>
  12:             <cfif Variables.tpShipping NEQ "UC"><input type="hidden" name="tipo_frete" value="#Variables.tpShipping#"></cfif>
  13:             <cfif Variables.vlExtras NEQ 0><input type="hidden" name="extras" value="#parseCurrency(Variables.vlExtras)#"></cfif>
  14:             
  15:             <cfloop from="1" to="#ArrayLen(variables.cart)#" index="i">
  16:                 <input type="hidden" name="item_id_#i#" value="#variables.cart[i].idItem#">
  17:                 <input type="hidden" name="item_descr_#i#" value="#variables.cart[i].nmItem#">
  18:                 <input type="hidden" name="item_quant_#i#" value="#variables.cart[i].qtItem#">
  19:                 <input type="hidden" name="item_valor_#i#" value="#parseCurrency(variables.cart[i].vlItem)#">
  20:                 <cfif variables.cart[i].flFreeShipping>
  21:                     <input type="hidden" name="item_frete_#i#" value="0">
  22:                     <input type="hidden" name="item_peso_#i#" value="0">
  23:                 <cfelse>
  24:                     <input type="hidden" name="item_peso_#i#" value="#variables.cart[i].nbWeight#">
  25:                 </cfif>
  26:             </cfloop>
  27:             <cfif NOT structIsEmpty(Variables.userData)>
  28:                 <input type="hidden" name="cliente_nome" value="#Variables.userData.nmPerson#">
  29:                 <input type="hidden" name="cliente_email" value="#Variables.userData.dsEmail#">
  30:                 <input type="hidden" name="cliente_cep" value="#Variables.userData.nbPostalCode#">
  31:                 <input type="hidden" name="cliente_end" value="#Variables.userData.dsAddress#">
  32:                 <input type="hidden" name="cliente_num" value="#Variables.userData.nbAddress#">
  33:                 <input type="hidden" name="cliente_compl" value="#Variables.userData.dsComplement#">
  34:                 <input type="hidden" name="cliente_bairro" value="#Variables.userData.dsDistrict#">
  35:                 <input type="hidden" name="cliente_cidade" value="#Variables.userData.dsCity#">
  36:                 <input type="hidden" name="cliente_uf" value="#Variables.userData.cdState#">
  37:                 <input type="hidden" name="cliente_pais" value="#Variables.userData.cdCountry#">
  38:                 <input type="hidden" name="cliente_ddd" value="#Variables.userData.cdDDD#">
  39:                 <input type="hidden" name="cliente_tel" value="#Variables.userData.nbTelephone#">
  40:             </cfif>
  41:         </form>
  42:         </cfoutput>
  43:         <script type="text/javascript">
   1:  
   2:             var objForm = document.getElementById("frmPagSeguro");
   3:             objForm.submit();
   4:         
</script>
  44:     </cfsavecontent>
  45:     <cfreturn returnVal>
  46: </cffunction>
A programação do método send é algo que se pode chamar de realmente simples. Ele vai gerar o nosso formulário, que nesse caso estou chamando de "frmPagSeguro", e executando o submit dele via javaScript. Isso esta sendo feito, para evitar o exemplo onde um simples "exibir código fonte" pode colocar toda a transação a perder.

Com isso estamos integrados ao PagSeguro, a página pagSeguro.cfm mostra, como o envio fica realmente simples.

pagSeguro.cfm
   1: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   2: <html xmlns="http://www.w3.org/1999/xhtml">
   3: <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   4: <title>Confirmação de Compra</title>
   5: </head>
   6: <body>
   7: <cfsetting showdebugoutput="false">
   8: <cfset aCart = session.shoppingCart.list()>
   9: <table border="1">
  10:     <thead>
  11:         <tr>
  12:             <th>Cód</th>
  13:             <th>Nome</th>
  14:             <th>Valor</th>
  15:             <th>Quantidade</th>
  16:             <th>Sub-Total</th>
  17:         </tr>
  18:     </thead>
  19:     <tfoot>
  20:         <tr>
  21:             <td colspan="5"><strong>Valor Total:</strong><cfoutput>#lsCurrencyFormat(session.shoppingCart.getTotal())#</cfoutput></td>
  22:         </tr>
  23:     </tfoot>
  24:     <cfoutput>
  25:     <tbody>
  26:         <cfloop array="#aCart#" index="cartItem">
  27:             <tr>
  28:                 <td>#cartItem.cdItem#</td>
  29:                 <td>#cartItem.nmItem#</td>
  30:                 <td>#lsCurrencyFormat(cartItem.vlItem)#</td>
  31:                 <td>#cartItem.qtItem#</td>
  32:                 <td>#lsCurrencyFormat(cartItem.vlTotalItem)#</td>
  33:             </tr>
  34:         </cfloop>
  35:     </tbody>
  36:     </cfoutput>
  37: </table>
  38: <form method="post">
  39:     <input type="submit" name="go" value="Confirmar Compra"/>
  40: </form>
  41: <cfif structKeyExists(form, "go")>
  42:     <cfset objPagSeguro = createObject("component", "PagSeguro")>
  43:     <cfset objPagSeguro.setCart(session.shoppingCart)>
  44:     <cfset objPagSeguro.setClient("Rafael Bandeira Rodrigues"
  45:         , "rafael_rodrigues@flagnet.inf.br"
  46:         , "00000000"
  47:         , "R. Onde eu moro"
  48:         , "Bairro"
  49:         , "Rio de Janeiro"
  50:         , "RJ"
  51:         , "21"
  52:         , "3333-3333")>
  53: <cfoutput>#objPagSeguro.send()#</cfoutput>
  54: </cfif>
  55:  
  56: </body>
  57: </html>
Agora vem a pergunta: "E o retorno automático?". Bom esse mistério será desvendado no post de amanhã.

E finalmente, para quem cansou de ler, esta tudo pronto para download no link http://www.flagnet.inf.br/downloads/shoppingCart-part2.rar