Ricerca…


Osservazioni

Questo esempio mostra un pratico esempio end-to-end di creazione di un pagamento futuro PayPal da un dispositivo Android, utilizzando un server Node.

Passaggio 1 di Android: configurazione, inizializzazione e gestione della risposta del server

Il codice di esempio completo per questa applicazione (server Android + Node) è disponibile nel repository Github per sviluppatori PayPal .

La prima fase della creazione della parte Android della nostra applicazione consiste nell'impostare un layout di base e gestire le risposte provenienti dal server che configureremo nel nodo.

Inizia creando un nuovo oggetto PayPalConfiguration per ospitare le informazioni dell'applicazione.

private static PayPalConfiguration config = new PayPalConfiguration()
        .environment(PayPalConfiguration.ENVIRONMENT_SANDBOX)
        .clientId("YOUR APPLICATION CLIENT ID")
        .merchantName("My Store")
        .merchantPrivacyPolicyUri(Uri.parse("https://www.example.com/privacy"))
        .merchantUserAgreementUri(Uri.parse("https://www.example.com/legal"));

Successivamente, aggiungiamo un semplice pulsante a onCreate(...) per fungere da nostro avvio di pagamento. Questo è semplicemente per innescare l'azione, e dovrebbe essere inserito come processo di avvio per la creazione di un pagamento futuro per un utente (ad esempio quando concordano su un abbonamento).

@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final Button button = (Button) findViewById(R.id.paypal_button);
}

Sotto res > layout > activity_main.xml aggiungiamo la definizione per il pulsante con la sua azione associata, quando viene cliccato chiama beginFuturePayment(...) , che definiremo tra un minuto.

<Button android:id="@+id/paypal_button"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:text="@string/paypal_button"
    android:onClick="beginFuturePayment" />

Sotto res > values > strings.xml aggiungiamo quindi una stringa di riferimento per il pulsante.

<string name="paypal_button">Process Future Payment</string>

Ora aggiungiamo il gestore di pulsanti, per avviare la chiamata per iniziare il processo di pagamento futuro quando l'utente fa clic sul pulsante. Quello che stiamo facendo qui è avviare il servizio di pagamento con l'oggetto di configurazione che abbiamo impostato all'inizio di questo esempio.

public void beginFuturePayment(View view){
    Intent serviceConfig = new Intent(this, PayPalService.class);
    serviceConfig.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
    startService(serviceConfig);

    Intent intent = new Intent(this, PayPalFuturePaymentActivity.class);
    intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
    startActivityForResult(intent, 0);
}

Quando viene avviata la chiamata per effettuare un pagamento futuro, verranno fornite alcune informazioni che dovranno essere inviate al nostro server. authCode queste informazioni dalla richiesta di pagamento valida in futuro ( authCode e metadataId ), quindi authCode la richiesta async al server per completare il pagamento futuro (dettagliato nel passaggio 2).

@Override
protected void onActivityResult (int requestCode, int resultCode, Intent data){
    if (resultCode == Activity.RESULT_OK){
        PayPalAuthorization auth = data.getParcelableExtra(PayPalFuturePaymentActivity.EXTRA_RESULT_AUTHORIZATION);
        if (auth != null){
            try{
                //prepare params to be sent to server
                String authCode = auth.getAuthorizationCode();
                String metadataId = PayPalConfiguration.getClientMetadataId(this);
                String [] params = {authCode, metadataId};

                //process async server request for token + payment
                ServerRequest req = new ServerRequest();
                req.execute(params);

            } catch (JSONException e) {
                Log.e("FPSample", "JSON Exception: ", e);
            }
        }
    } else if (resultCode == Activity.RESULT_CANCELED) {
        Log.i("FPSample", "User canceled.");
    } else if (resultCode == PayPalFuturePaymentActivity.RESULT_EXTRAS_INVALID) {
        Log.i("FPSample", "Invalid configuration");
    }
}

Infine, definiamo il nostro onDestroy() .

@Override
public void onDestroy(){
    stopService(new Intent(this, PayPalService.class));
    super.onDestroy();
}

Passaggio 2 di Android: richiesta server asincrono

Il codice di esempio completo per questa applicazione (server Android + Node) è disponibile nel repository Github per sviluppatori PayPal .

A questo punto è stato fatto clic sul pulsante di pagamento futuro di PayPal, abbiamo un codice di autenticazione e ID di metadati dall'SDK di PayPal e dobbiamo trasferirli sul nostro server per completare la procedura di pagamento futura.

Nel processo in background di seguito, stiamo facendo alcune cose:

  • /fpstore l'URI che per il nostro server sia http://10.0.2.2:3000/fpstore , che sta colpendo l'endpoint /fpstore del nostro server in esecuzione su localhost.
  • Viene quindi impostato l'oggetto JSON che verrà inviato, che contiene il codice di autenticazione e l'ID dei metadati.
  • La connessione viene quindi effettuata. Nel caso di una richiesta riuscita (intervallo 200/201), possiamo aspettarci una risposta dal server. Leggiamo questa risposta e poi la restituiamo.
  • Infine, abbiamo un onPostExecute(...) impostato per gestire la stringa del server restituito. Nel caso di questo esempio, è semplicemente registrato.
public class ServerRequest extends AsyncTask<String, Void, String> {
    protected String doInBackground(String[] params){
        HttpURLConnection connection = null;
        try{
            //set connection to connect to /fpstore on localhost
            URL u = new URL("http://10.0.2.2:3000/fpstore");
            connection = (HttpURLConnection) u.openConnection();
            connection.setRequestMethod("POST");

            //set configuration details
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty("Accept", "application/json");
            connection.setAllowUserInteraction(false);
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(10000);

            //set server post data needed for obtaining access token
            String json = "{\"code\": \"" + params[0] + "\", \"metadataId\": \"" + params[1] + "\"}";
            Log.i("JSON string", json);

            //set content length and config details
            connection.setRequestProperty("Content-length", json.getBytes().length + "");
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(false);

            //send json as request body
            OutputStream outputStream = connection.getOutputStream();
            outputStream.write(json.getBytes("UTF-8"));
            outputStream.close();

            //connect to server
            connection.connect();

            //look for 200/201 status code for received data from server
            int status = connection.getResponseCode();
            switch (status){
                case 200:
                case 201:
                    //read in results sent from the server
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                    StringBuilder sb = new StringBuilder();
                    String line;
                    while ((line = bufferedReader.readLine()) != null){
                        sb.append(line + "\n");
                    }
                    bufferedReader.close();

                    //return received string
                    return sb.toString();
            }

        } catch (MalformedURLException ex) {
            Log.e("HTTP Client Error", ex.toString());
        } catch (IOException ex) {
            Log.e("HTTP Client Error", ex.toString());
        } catch (Exception ex) {
            Log.e("HTTP Client Error", ex.toString());
        } finally {
            if (connection != null) {
                try{
                    connection.disconnect();
                } catch (Exception ex) {
                    Log.e("HTTP Client Error", ex.toString());
                }
            }
        }
        return null;
    }

    protected void onPostExecute(String message){
        //log values sent from the server - processed payment
        Log.i("HTTP Client", "Received Return: " + message);
    }
}

Passaggio 3 di Android: Node Server per ottenere token di accesso e pagamento di processo

Il codice di esempio completo per questa applicazione (server Android + Node) è disponibile nel repository Github per sviluppatori PayPal .

Dal passaggio 2, è stata /fpstore una richiesta asincrona al nostro server /fpstore , passando il codice di autenticazione e l'ID dei metadati. Ora dobbiamo scambiarli con un token per completare la richiesta ed elaborare il pagamento futuro.

Per prima cosa impostiamo le nostre variabili di configurazione e l'oggetto.

var bodyParser = require('body-parser'),
    http = require('http'),
    paypal = require('paypal-rest-sdk'),
    app = require('express')();

var client_id = 'YOUR APPLICATION CLIENT ID';
var secret = 'YOUR APPLICATION SECRET';

paypal.configure({
    'mode': 'sandbox',
    'client_id': client_id,
    'client_secret': secret
});

app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json());

Ora impostiamo una rotta Express che ascolterà le richieste POST inviate /fpstore dal nostro codice Android.

Stiamo facendo una serie di cose in questo percorso:

  • Acquisiamo il codice di autenticazione e l'ID dei metadati dal corpo del POST.
  • Quindi facciamo una richiesta a generateToken() , passando attraverso l'oggetto codice. In caso di successo, otteniamo un token che può essere utilizzato per creare il pagamento.
  • Successivamente, gli oggetti config vengono creati per il pagamento futuro che deve essere fatto e viene payment.create(...) una richiesta a payment.create(...) , passando lungo i futuri oggetti di pagamento e di configurazione del pagamento. Questo crea il pagamento futuro.
app.post('/fpstore', function(req, res){
    var code = {'authorization_code': req.body.code};
    var metadata_id = req.body.metadataId;
    
    //generate token from provided code
    paypal.generateToken(code, function (error, refresh_token) {
        if (error) {
            console.log(error);
            console.log(error.response);
        } else {
            //create future payments config 
            var fp_config = {'client_metadata_id': metadata_id, 'refresh_token': refresh_token};

            //payment details
            var payment_config = {
                "intent": "sale",
                "payer": {
                    "payment_method": "paypal"
                },
                "transactions": [{
                    "amount": {
                        "currency": "USD",
                        "total": "3.50"
                    },
                    "description": "Mesozoic era monster toy"
                }]
            };

            //process future payment
            paypal.payment.create(payment_config, fp_config, function (error, payment) {
                if (error) {
                    console.log(error.response);
                    throw error;
                } else {
                    console.log("Create Payment Response");
                    console.log(payment);
                    
                    //send payment object back to mobile
                    res.send(JSON.stringify(payment));
                }
            });
        }
    });
});

Infine, creiamo il server per ascoltare sulla porta 3000.

//create server
http.createServer(app).listen(3000, function () {
   console.log('Server started: Listening on port 3000');
});


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow