JSR 229: Mobile Payment API - Exemplo

2 respostas
liclopes

Um novo canal de comércio, o de pagamentos móveis (m-payment)

Empresas como a MTV, a Fox Entertainment, a NBC, a LOreal e a Nike já aceitam pagamentos via mobile PenPal. As operações são feitas via portal WAP da PenPal desenvolvido para mobile payment. O Banco do Brasil e o Google já está entrando na onda.

Exemplo oficial da API

import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.payment.TransactionListener;
import javax.microedition.payment.TransactionModule;
import javax.microedition.payment.TransactionRecord;
import javax.microedition.payment.TransactionModuleException;

public class MyGame extends MIDlet implements TransactionListener, CommandListener {
  private TransactionModule transModulo;
  private int aNivel = 0;
  private int nbNivel = 0;
  private int MAX_NIVEL = 3;
  private Display tela;
  private Command sair;

  public MyGame(){
    tela = Display.getDisplay(this);
    Form formMain = new Form("GamePay");
    sair = new Command("Exit", Command.EXIT, 1);
    formMain.addCommand(sair);
    formMain.setCommandListener(this);
    tela.setCurrent(formMain);

    try {
      transModulo = new TransactionModule(this);
    }
    catch(TransactionModuleException e) {
      /* O módulo do pagamento indica que recusou uma conexão de TransactionModule. 
      Possíveis motivos: os dados da provisão estão errados ou incompletos ou que há conexões excessivas ligadas a esse módulo de pagamento */
      e.toString();
    }
    catch(Exception e) { }

    try {
      transModulo.setListener(this);
    } catch(Exception e) { }
  }
 
  public void startApp(){
    while (nbNivel &lt= MAX_NIVEL) {
    // pagamento (payment) obrigatório p/ o nível
    try {
      transModulo.process(aNivel, "Prox Nível", "Libera o acesso ao nível seguinte.");
      synchronized(this) {
        try {
          wait(); // esperar até que a rechamada seja feita
        }
        catch (InterruptedException ie) { }
      }
    }
    catch (Exception e) { }
    // início do nível
    Form formLevel = new Form("Nivel " + nbNivel);
    tela.setCurrent(formLevel);
    try {
      Thread.sleep(5000);
    } 
    catch (InterruptedException e1) {
      el.getMessage()
    }
    // fim do nível
    nbNivel++;
    }
  }


  public void processed(TransactionRecord record){
    switch(record.getState()) {
      case TransactionRecord.TRANSACTION_SUCCESSFUL:
      // transação de pagamento bem sucedida
      break;
      case TransactionRecord.TRANSACTION_REJECTED:
      // transação de pagamento mal sucedida, deve-se pagar para jogar
      break;
      case TransactionRecord.TRANSACTION_FAILED:
      default:
      // problemas técnicos - tente de novo
      break;
    }
    synchronized(this) {
      notify(); // notifica emquanto espera thread
    }
  }

  protected void pauseApp() { }

  protected void destroyApp(boolean arg0) { }

  public void commandAction(Command command, Displayable telaable){
    if (command == sair) {
      destroyApp(true);
      notifyDestroyed();
    }
  }
}

Pequeno exemplo 2

import javax.microedition.payment.*;
...
public class MyGame extends MIDlet implements TransactionListener, CommandListener {
  private TransactionModule myTransactionModule;
  public GamePay2(){
    ...
    try {
      myTransactionModule = new TransactionModule(this);
    }
    catch(TransactionModuleException e) { }
    try {
      myTransactionModule.setListener(this);
    }
    catch(Exception e) { }
  }

  public void startApp(){
    ...
    try {
      myTransactionModule.process(caracteristicasID, ?Titulo de Caracteristicas", "Descrição das  Caracteristicas");
      synchronized(this) {
        try {
          wait(); // espere enquanto a rechamada é realizada
        }
        catch (InterruptedException ie) { }
      }
    }
    catch (Exception e) { }
    ...
  }  

  public void processed(TransactionRecord myPaytRecord){
    switch(myPayRecord.getState()) {
      case TransactionRecord.TRANSACTION_SUCCESSFUL:
        // transação de pagamento bem sucedida
        break;
      case TransactionRecord.TRANSACTION_REJECTED:
        // transação de pagamento rejeitado
        break;
      case TransactionRecord.TRANSACTION_FAILED:
        default:
        // problemas técnicos - tente novamente
        break;
      }
      ...
  }
}

Mais info em: https://sdlc5a.sun.com/ECom/EComActionServlet;jsessionid=EA44F16E59366B5928347F1515619CFB
Site oficial -&gt http://jcp.org/en/jsr/detail?id=229

Arquivo JAD:
Pay-Version: 1.0
Pay-Adapters: PPSMS, X-TEST
MIDlet-Permissions: javax.microedition.payment.process.jpp
MIDlet-Certificate-<n>-<m>: <base64 encoding of a certificate>
MIDlet-Jar-RSA-SHA1: <base64 encoded Jar signature>

Arquivo JAR-Manifest:
Pay-Version: 1.0
Pay-Update-Stamp: 2004-11-15 02:00+01:00
Pay-Providers: SMS1, Test1Card
Pay-Update-URL: http://<update-site>/thisgame.manifest.jpp
Pay-Cache: no
Pay-Feature-0: 0
Pay-Feature-1: 0
Pay-Feature-2: 1
Pay-SMS1-Info: PPSMS, EUR, 928, 99
Pay-SMS1-Tag-0: 1.20, 9990000, 0x0cba98765400
Pay-SMS1-Tag-1: 2.50, 9990000, 0x0cba98765401, 2
Pay-Test1Card-Info: X-TEST8, EUR, c4d21, soap://<soap-site-1>/
Pay-Test1Card-Tag-0: 1.21
Pay-Test1Card-Tag-1: 2.46

Um exemplo complexo do arquivo JAR-Manifest:
Pay-Version: 1.0
Pay-Update-Stamp: 2004-11-15 02:00+01:00
Pay-Providers: SONERA, RADIOG, DNSDNA
Pay-Update-URL: http://<update-site>/thisgame.manifest.jpp
Pay-Cache: no
Pay-Feature-0: 0
Pay-Feature-1: 0
Pay-Feature-2: 1

If user?s operator is ?Sonera?, MNC=928, MCC=99

Pay-SONERA-Info: PPSMS, EUR, 928, 99
Pay-SONERA-Tag-0: 1.20, 9990000, 0x0cba98765400
Pay-SONERA-Tag-1: 2.50, 9990000, 0x0cba98765401, 2

If user?s operator is ?RadioG?, MNC=747, MCC=88

Pay-RADIOG-Info: PPSMS, EUR, 747, 88
Pay-RADIOG-Tag-0: 1.21, 34501, 0xf9b500
Pay-RADIOG-Tag-1: 2.49, 34502, 0xf9b501, 3

If user?s operator is ?DNSDNA?, MNC=380, MCC=77

Pay-DNSDNA-Info: PPSMS, EUR, 380, 77
Pay-DNSDNA-Tag-0: 1.41, 19076501, _DNS
Pay-DNSDNA-Tag-1: 1.99, 19023202, _DNS

Uma alternativa p/ quem precisa realizar um pagamento mas não possui a JSR 229 no aparelho, pode usar conexões HTTPS e post

import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.io.*;
import javax.microedition.lcdui.*;

public class SslTest extends MIDlet implements CommandListener {
  private final String merchant="4181607";
  private final String amount="19095";
  private final String currency="208";
  private final String orderid ="991002b";
  private final String accepturl ="https://payment.architrade.com/cgissl/relay.cgi/http://www.java4mobile/dibs/godkendt.jsp";
  private final String declineurl ="https://payment.architrade.com/cgissl/relay.cgi/http://www.java4mobile/dibs/afvist.jsp";
  private final String test="foo";

  private String cardno;
  private String expmon;
  private String expyear;
  private String cvc;
  private String url = "https://payment.architrade.com/cgi-ssl/auth.cgi";
  private String post;
  private String urlTotal; 

  private Command exitCommand = new Command("Exit", Command.EXIT, 2);
  private Command getCommand = new Command("Pay", Command.SCREEN, 1);
  private Form form;
  private TextField txtCardno = new TextField("Card no:", null , 16, TextField.NUMERIC);
  private TextField txtExpmon = new TextField("Expmon", null, 2, TextField.NUMERIC);
  private TextField txtExpyear = new TextField("Expyear", null , 2, TextField.NUMERIC);
  private TextField txtCvc = new TextField("Cvc", null, 3, TextField.NUMERIC);
  private Display display; 

  public SslTest() { }

  public void startApp() {
    if (display == null)
      display = Display.getDisplay(this);
    form = new Form("Payment");
    form.append(txtCardno);
    form.append(txtExpmon);
    form.append(txtExpyear);
    form.append(txtCvc);
    form.addCommand(exitCommand);
    form.addCommand(getCommand);
    form.setCommandListener(this);
    display.setCurrent(form);
  }

  public void commandAction(Command c, Displayable d) {
    if (c == exitCommand) {
      notifyDestroyed();
    } 
    else if (c == getCommand) {
      cardno=txtCardno.getString();
      expmon=txtExpmon.getString();
      expyear=txtExpyear.getString();
      cvc=txtCvc.getString();
      post = "?merchant="+merchant+"&amount="+amount+"&currency="+currency+"&orderid="+orderid+ "&accepturl="+accepturl+"&declineurl="+declineurl+"&cardno="+cardno+"&expmon="+expmon+ "&expyear="+expyear+"&cvc="+cvc+"&test="+test;
      StringBuffer b = new StringBuffer();
      HttpsConnection con = null;
      InputStream is = null;
      OutputStream os = null;
      urlTotal = url+post;

      try {
        int len = 0;
        int ch = 0;
        con = (HttpsConnection)Connector.open(urlTotal);
        con.setRequestMethod(HttpsConnection.POST);
        /*
         byte[] data = post.getBytes();
         con.setRequestProperty("Content-Length",
         Integer.toString(data.length));
         os = con.openOutputStream();
         os.write( data );
         os.close();
       */
       System.out.println(Integer.toString(con.getResponseCode()));
       is = con.openInputStream();
       len = (int) con.getLength();
       if (len != -1) {
         for(int i=0; i&lt;len; i++) {
           if((ch = is.read()) != -1) {
             b.append((char) ch);
           }
         }
       }

        else {
          while((ch = is.read()) != -1) {
            len = is.available();
            b.append((char) ch);
          }
        }

       System.out.println("Response: " +b.toString()); 
       Alert a = new Alert("Trans results:", b.toString(), null, null);
       a.setTimeout(Alert.FOREVER);
       display.setCurrent(a);
     }
     catch (Exception e) {
       e.printStackTrace();
       String s = e.toString();
       If(s != null) {
         Alert aa = new Alert("Error in connection:", s, null, null);
         aa.setTimeout(Alert.FOREVER);
         display.setCurrent(aa);
       }
     }

     finally {
     if (is != null) {
       try {
         is.close();
       }
       catch (Exception ce) { }
     }
     if (c != null) {
       try {
         con.close();
       }
       catch (Exception ce) { }
     }
   }
 }
}

 public void pauseApp() {}

 public void destroyApp(boolean unconditional) { }

}

Mais info em: Analysis of J2ME for developing Mobile Payment Systems -> www.microjava.com/articles/techtalk/mpayment

P/ testar se a API é suportada pelo aparelho

import javax.microedition.lcdui.Command;   
import javax.microedition.lcdui.CommandListener;   
import javax.microedition.lcdui.Display;   
import javax.microedition.lcdui.Displayable;   
import javax.microedition.lcdui.Form;   
import javax.microedition.midlet.MIDlet;   
  
public class JSRTest extends MIDlet implements Runnable,CommandListener{   
    Form form;   
    Thread thread;   
    Command c=new Command("Exit",Command.EXIT,0);   
    public JSRTest()   
    {   
        Display.getDisplay(this).setCurrent(form=new Form("JSR Test"));   
        form.addCommand(c);   
        form.setCommandListener(this);   
        (thread=new Thread(this)).start();   
    }   
    protected void destroyApp(boolean u){   
        super.notifyDestroyed();   
    }   
    protected void pauseApp() {   
    }   
    protected void startApp(){   
    }   
    public void run() {   
        checkJSR("MIDP2.0","javax.microedition.lcdui.game.GameCanvas");   
        checkJSR("CLDC1.1","java.lang.Float");   
        checkJSR("MMAPI","javax.microedition.media.Player");   
        checkJSR("WMAPI","javax.wireless.messaging.Message");   
        checkJSR("JSR75","javax.microedition.io.file.FileConnection");   
        checkJSR("JSR082","javax.bluetooth.UUID");   
        checkJSR("JSR179","javax.microedition.location.Location");   
        checkJSR("JSR180","javax.microedition.sip.SipConnection");   
        checkJSR("JSR184","javax.microedition.m3g.Mesh");   
        checkJSR("JSR211","javax.microedition.content.Registry");   
        checkJSR("JSR226","javax.microedition.m2g.SVGImage");   
        checkJSR("JSR229","javax.microedition.payment.TransactionRecord");   
        checkJSR("JSR234","javax.microedition.amms.Module");   
        checkJSR("JSR238","javax.microedition.global.Formatter");   
        checkJSR("JSR239","javax.microedition.khronos.egl.EGL");   
    }   
    private void checkJSR(String jsr,String className)   
    {   
        try {   
            Class.forName(className);   
            form.append(jsr+" Supproted\n");   
        } catch (ClassNotFoundException e) {   
            form.append(jsr+" Not Supproted\n");   
        }   
    }   
    public void commandAction(Command cmd, Displayable disp) {   
        this.destroyApp(false);   
    }   
}

2 Respostas

P

Cade o uso da API Payment ?

Pra mim isto é simplesmente mostra o uso do HTTPS…

liclopes

A JCP definiu uma API para iniciar transações do pagamento de uma maneira segura.
A API é um agnóstico adaptador de pagamentos, isto é, um suporte ao protocolo real de pagamento (SMS, cartão de crédito,?)

já arrumei

Criado 12 de setembro de 2007
Ultima resposta 14 de set. de 2007
Respostas 2
Participantes 2