APIs e Microsserviços

20 dez, 2012

Implementação de Market Place em Java

Publicidade

No tutorial Implementação de Market Place com Adaptive Payments falamos sobre a operação Pay para definição de pagamentos paralelos ou encadeados.

Nesse tutorial veremos como implementar a operação Pay utilizando Java, criando uma biblioteca para ser utilizada por nossas aplicações.

Para facilitar o trabalho de configuração da operação Pay, podemos criar uma classe AdaptivePayments que além de configurar a requisição HTTP, criará a instância da operação:

package com.paypal.x.adaptivepayments;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.HttpsURLConnection;
public class AdaptivePayments {
    public final static String HOST = "svcs.paypal.com";
    public final static String SANDBOX_APPID = "APP-80W284485P519543T";
    public final static String SANDBOX_HOST = "svcs.sandbox.paypal.com";
    private String appId;
    private String userId;
    private String password;
    private String signature;
    private Boolean sandbox;
    public AdaptivePayments(String appId, String userId, String password,
            String signature) {
        this.appId = appId;
        this.userId = userId;
        this.password = password;
        this.signature = signature;
        this.sandbox = appId.equals(SANDBOX_APPID);
    }
    public AdaptivePayments(String userId, String password, String signature) {
        this(SANDBOX_APPID, userId, password, signature);
    }
    public Map<String, String> execute(AdaptivePaymentsOperation o) {
        Map<String, String> requestNvp = o.getNvp();
        Map<String, String> responseNvp = new HashMap<String, String>();
        StringBuilder sb = new StringBuilder();
        sb.append("https://");
        sb.append(sandbox ? SANDBOX_HOST : HOST);
        sb.append("/AdaptivePayments/");
        sb.append(o.getOperation());
        HttpsURLConnection conn = getConnection(sb.toString());
        try {
            conn.setRequestProperty("X-PAYPAL-SECURITY-USERID", userId);
            conn.setRequestProperty("X-PAYPAL-SECURITY-PASSWORD", password);
            conn.setRequestProperty("X-PAYPAL-SECURITY-SIGNATURE", signature);
            conn.setRequestProperty("X-PAYPAL-APPLICATION-ID", appId);
            conn.setRequestProperty("X-PAYPAL-REQUEST-DATA-FORMAT", "NV");
            conn.setRequestProperty("X-PAYPAL-RESPONSE-DATA-FORMAT", "NV");
            OutputStreamWriter writer = new OutputStreamWriter(
                    conn.getOutputStream());
            sb = new StringBuilder();
            for (Entry<String, String> nvp : requestNvp.entrySet()) {
                sb.append(nvp.getKey());
                sb.append("=");
                sb.append(URLEncoder.encode(nvp.getValue(), "UTF-8"));
                sb.append("&");
            }
            sb.append( "requestEnvelope.errorLanguage=en_US" );
            writer.write(sb.toString());
            writer.flush();
            writer.close();
            InputStreamReader in = new InputStreamReader(conn.getInputStream());
            try {
                sb = new StringBuilder();
                BufferedReader reader = new BufferedReader(in);
                String data = null;
                while ((data = reader.readLine()) != null) {
                    sb.append(data);
                }
                data = sb.toString();
                String pairs[] = data.split("&");
                for (String current : pairs) {
                    String[] pair = current.split("=");
                    responseNvp.put(pair[0],
                            URLDecoder.decode(pair[1], "UTF-8"));
                }
            } finally {
                try {
                    in.close();
                } catch (IOException ignored) {
                }
            }
        } catch (IOException e) {
            Logger.getLogger(AdaptivePayments.class.getName()).log(
                    Level.SEVERE, null, e);
        }
        return responseNvp;
    }
    protected HttpsURLConnection getConnection(String spec) {
        URL url;
        HttpsURLConnection conn;
        try {
            url = new URL(spec);
            conn = (HttpsURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            return conn;
        } catch (IOException e) {
            Logger.getLogger(AdaptivePayments.class.getName()).log(
                    Level.SEVERE, null, e);
        }
        return null;
    }
    public PayOperation pay() {
        return pay("PAY");
    }
    public PayOperation pay(String actionType) {
        PayOperation payOperation = new PayOperation(this);
        payOperation.setActionType(actionType);
        return payOperation;
    }
}
Com a classe AdaptivePayments definida, podemos definir uma base para as operações da API:
package com.paypal.x.adaptivepayments;

import java.util.HashMap;
import java.util.Map;
public abstract class AdaptivePaymentsOperation {
    private AdaptivePayments ap;
    private Map<String, String> nvp;
    public AdaptivePaymentsOperation(AdaptivePayments ap) {
        this.ap = ap;
        nvp = new HashMap<String, String>();
    }
    public Map<String, String> execute() {
        return ap.execute(this);
    }
    Map<String, String> getNvp() {
        return nvp;
    }
    abstract String getOperation();
}
Com isso, a definição da operação Pay fica simples:
package com.paypal.x.adaptivepayments;

import java.util.ArrayList;
import java.util.List;
public class PayOperation extends AdaptivePaymentsOperation {
    private List<Receiver> receiverList;
    public PayOperation(AdaptivePayments ap) {
        super(ap);
        receiverList = new ArrayList<Receiver>();
    }
    @Override
    String getOperation() {
        return "Pay";
    }
    public Receiver receiverList(Integer n) {
        if (receiverList.size() == n) {
            receiverList.add(new Receiver(this, n));
        }
        return receiverList.get(n);
    }
    public void setActionType(String actionType) {
        getNvp().put("actionType", actionType);
    }
    public void setCancelUrl(String cancelUrl) {
        getNvp().put("cancelUrl", cancelUrl);
    }
    public void setCurrencyCode(String currencyCode) {
        getNvp().put("currencyCode", currencyCode);
    }
    public void setReturnUrl(String returnUrl) {
        getNvp().put("returnUrl", returnUrl);
    }
}
Como podemos ver, o método receiverList funciona como acesso e criação de instâncias de Receiver, que é definido abaixo:
package com.paypal.x.adaptivepayments;

public class Receiver {
    private Integer n;
    private AdaptivePaymentsOperation o;
    public Receiver(AdaptivePaymentsOperation o, Integer n) {
        this.o = o;
        this.n = n;
    }
    public void setAmount(Integer amount) {
        o.getNvp().put("receiverList.receiver(" + n + ").amount",
                amount.toString());
    }
    public void setAmount(Double amount) {
        o.getNvp().put("receiverList.receiver(" + n + ").amount",
                amount.toString());
    }
    public void setEmail(String email) {
        o.getNvp().put("receiverList.receiver(" + n + ").email", email);
    }
    public void setPrimary(Boolean primary) {
        o.getNvp().put("receiverList.receiver(" + n + ").primary",
                primary ? "true" : "false");
    }
}
Com isso podemos utilizar a operação Pay como abaixo:
package com.paypal.x.adaptivepayments;

import java.util.Map;
public class CodeSample {
    /**
     * @param args
     */
    public static void main(String[] args) {
        String userId = "usuario";
        String password = "senha";
        String signature = "assinatura";
        AdaptivePayments ap = new AdaptivePayments(userId, password, signature);
        PayOperation pay = ap.pay();
        pay.setCurrencyCode( "USD" );
        pay.setCancelUrl("http://127.0.0.1:8080/cancel");
        pay.setReturnUrl("http://127.0.0.1:8080/return");
        pay.receiverList(0).setAmount(100);
        pay.receiverList(0).setEmail("neto_1306507007_biz@gmail.com");
        pay.receiverList(0).setPrimary(true);
        pay.receiverList(1).setAmount(100);
        pay.receiverList(1).setEmail("neto.j_1324471857_biz@gmail.com");
        Map<String, String> nvp = pay.execute();
        if (nvp.containsKey("responseEnvelope.ack")
                && nvp.get("responseEnvelope.ack").equals("SUCCESS")) {
            String payKey = nvp.get("payKey");
            System.out.println(payKey);
        }
    }
}
Como estamos falando da plataforma Java, esse mesmo código pode ser utilizado em desktop, server-side com J2EE ou dispositivos móveis, como tablets ou celulares Android. Cada um desses ambientes possuem seus próprios métodos para fazer o redirecionamento do usuário para o ambiente seguro do PayPal e, como são muitos ambientes diferentes, não vamos demonstrá-lo aqui.
De forma geral, quando a operação for bem sucedida, o campo payKey será retornado na resposta do PayPal e, com o valor desse campo, criamos a URL de redirecionamento como abaixo:
[code]

O código do exemplo pode ser encontrado em Code Sample

Nota: Os códigos de exemplo são meramente ilustrativos, com o intuito de demonstrar a facilidade de integração com a API. Apesar de funcionarem segundo a proposta do tutorial, devem ser tratados como exemplos e não como código de produção.