JSR 229: Mobile Payment API - Exemplo

0 respostas
L

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 <= 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 &#123;
  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&#58;//payment.architrade.com/cgissl/relay.cgi/http&#58;//www.java4mobile/dibs/godkendt.jsp";
  private final String declineurl ="https&#58;//payment.architrade.com/cgissl/relay.cgi/http&#58;//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&#58;//payment.architrade.com/cgi-ssl/auth.cgi";
  private String post;
  private String urlTotal; 

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

  public SslTest&#40;&#41; &#123; &#125;

  public void startApp&#40;&#41; &#123;
    if &#40;display == null&#41;
      display = Display.getDisplay&#40;this&#41;;
    form = new Form&#40;"Payment"&#41;;
    form.append&#40;txtCardno&#41;;
    form.append&#40;txtExpmon&#41;;
    form.append&#40;txtExpyear&#41;;
    form.append&#40;txtCvc&#41;;
    form.addCommand&#40;exitCommand&#41;;
    form.addCommand&#40;getCommand&#41;;
    form.setCommandListener&#40;this&#41;;
    display.setCurrent&#40;form&#41;;
  &#125;

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

      try &#123;
        int len = 0;
        int ch = 0;
        con = &#40;HttpsConnection&#41;Connector.open&#40;urlTotal&#41;;
        con.setRequestMethod&#40;HttpsConnection.POST&#41;;
        /*
         byte&#91;&#93; data = post.getBytes&#40;&#41;;
         con.setRequestProperty&#40;"Content-Length",
         Integer.toString&#40;data.length&#41;&#41;;
         os = con.openOutputStream&#40;&#41;;
         os.write&#40; data &#41;;
         os.close&#40;&#41;;
       */
       System.out.println&#40;Integer.toString&#40;con.getResponseCode&#40;&#41;&#41;&#41;;
       is = con.openInputStream&#40;&#41;;
       len = &#40;int&#41; con.getLength&#40;&#41;;
       if &#40;len != -1&#41; &#123;
         for&#40;int i=0; i&amp;lt;len; i++&#41; &#123;
           if&#40;&#40;ch = is.read&#40;&#41;&#41; != -1&#41; &#123;
             b.append&#40;&#40;char&#41; ch&#41;;
           &#125;
         &#125;
       &#125;

        else &#123;
          while&#40;&#40;ch = is.read&#40;&#41;&#41; != -1&#41; &#123;
            len = is.available&#40;&#41;;
            b.append&#40;&#40;char&#41; ch&#41;;
          &#125;
        &#125;

       System.out.println&#40;"Response&#58; " +b.toString&#40;&#41;&#41;; 
       Alert a = new Alert&#40;"Trans results&#58;", b.toString&#40;&#41;, null, null&#41;;
       a.setTimeout&#40;Alert.FOREVER&#41;;
       display.setCurrent&#40;a&#41;;
     &#125;
     catch &#40;Exception e&#41; &#123;
       e.printStackTrace&#40;&#41;;
       String s = e.toString&#40;&#41;;
       If&#40;s != null&#41; &#123;
         Alert aa = new Alert&#40;"Error in connection&#58;", s, null, null&#41;;
         aa.setTimeout&#40;Alert.FOREVER&#41;;
         display.setCurrent&#40;aa&#41;;
       &#125;
     &#125;

     finally &#123;
     if &#40;is != null&#41; &#123;
       try &#123;
         is.close&#40;&#41;;
       &#125;
       catch &#40;Exception ce&#41; &#123; &#125;
     &#125;
     if &#40;c != null&#41; &#123;
       try &#123;
         con.close&#40;&#41;;
       &#125;
       catch &#40;Exception ce&#41; &#123; &#125;
     &#125;
   &#125;
 &#125;
&#125;

 public void pauseApp&#40;&#41; &#123;&#125;

 public void destroyApp&#40;boolean unconditional&#41; &#123; &#125;

&#125;

Mais info em: Analysis of J2ME for developing Mobile Payment Systems -&gt; 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&#123;   
    Form form;   
    Thread thread;   
    Command c=new Command&#40;"Exit",Command.EXIT,0&#41;;   
    public JSRTest&#40;&#41;   
    &#123;   
        Display.getDisplay&#40;this&#41;.setCurrent&#40;form=new Form&#40;"JSR Test"&#41;&#41;;   
        form.addCommand&#40;c&#41;;   
        form.setCommandListener&#40;this&#41;;   
        &#40;thread=new Thread&#40;this&#41;&#41;.start&#40;&#41;;   
    &#125;   
    protected void destroyApp&#40;boolean u&#41;&#123;   
        super.notifyDestroyed&#40;&#41;;   
    &#125;   
    protected void pauseApp&#40;&#41; &#123;   
    &#125;   
    protected void startApp&#40;&#41;&#123;   
    &#125;   
    public void run&#40;&#41; &#123;   
        checkJSR&#40;"MIDP2.0","javax.microedition.lcdui.game.GameCanvas"&#41;;   
        checkJSR&#40;"CLDC1.1","java.lang.Float"&#41;;   
        checkJSR&#40;"MMAPI","javax.microedition.media.Player"&#41;;   
        checkJSR&#40;"WMAPI","javax.wireless.messaging.Message"&#41;;   
        checkJSR&#40;"JSR75","javax.microedition.io.file.FileConnection"&#41;;   
        checkJSR&#40;"JSR082","javax.bluetooth.UUID"&#41;;   
        checkJSR&#40;"JSR179","javax.microedition.location.Location"&#41;;   
        checkJSR&#40;"JSR180","javax.microedition.sip.SipConnection"&#41;;   
        checkJSR&#40;"JSR184","javax.microedition.m3g.Mesh"&#41;;   
        checkJSR&#40;"JSR211","javax.microedition.content.Registry"&#41;;   
        checkJSR&#40;"JSR226","javax.microedition.m2g.SVGImage"&#41;;   
        checkJSR&#40;"JSR229","javax.microedition.payment.TransactionRecord"&#41;;   
        checkJSR&#40;"JSR234","javax.microedition.amms.Module"&#41;;   
        checkJSR&#40;"JSR238","javax.microedition.global.Formatter"&#41;;   
        checkJSR&#40;"JSR239","javax.microedition.khronos.egl.EGL"&#41;;   
    &#125;   
    private void checkJSR&#40;String jsr,String className&#41;   
    &#123;   
        try &#123;   
            Class.forName&#40;className&#41;;   
            form.append&#40;jsr+" Supproted\n"&#41;;   
        &#125; catch &#40;ClassNotFoundException e&#41; &#123;   
            form.append&#40;jsr+" Not Supproted\n"&#41;;   
        &#125;   
    &#125;   
    public void commandAction&#40;Command cmd, Displayable disp&#41; &#123;   
        this.destroyApp&#40;false&#41;;   
    &#125;   
&#125;
Criado 12 de setembro de 2007
Respostas 0
Participantes 1