Recherche…


Remarques

Cet exemple montre un exemple pratique de création d'un futur paiement PayPal à partir d'un périphérique Android, à l'aide d'un serveur de nœuds.

Etape 1: mise en page, initialisation et gestion des réponses du serveur

L'exemple de code complet pour cette application (serveur Android + Node) est disponible dans le référentiel Github de PayPal Developer .

La première étape de la création de la partie Android de notre application consiste à configurer une disposition de base et à gérer les réponses qui reviennent du serveur que nous allons configurer dans Node.

Commencez par créer un nouvel objet PayPalConfiguration pour héberger les informations de votre application.

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"));

Ensuite, nous ajoutons un simple bouton à onCreate(...) pour faire office d'initiation de paiement. Ceci est simplement pour déclencher l'action, et devrait être placé en tant que processus d'initiation pour créer un paiement futur pour un utilisateur (par exemple, quand ils s'accordent sur un abonnement).

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

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

Sous res > layout > activity_main.xml on ajoute la définition du bouton avec son action associée, quand on clique dessus, il appelle beginFuturePayment(...) , que nous définirons dans une minute.

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

Sous res > values > strings.xml nous ajoutons alors une référence de chaîne pour le bouton.

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

Maintenant, nous ajoutons le gestionnaire de bouton, pour lancer l'appel pour commencer le processus de paiement futur lorsque l'utilisateur clique sur le bouton. Ce que nous faisons ici est de démarrer le service de paiement avec l'objet de configuration que nous avons configuré en haut de cet exemple.

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);
}

Lorsque cet appel pour effectuer un paiement ultérieur est lancé, nous recevrons des informations qui devront être envoyées à notre serveur. Nous extrayons ces informations de la demande de paiement future valide ( authCode et metadataId ), puis authCode la demande asynchrone sur le serveur pour effectuer le paiement futur (détaillé à l'étape 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");
    }
}

Enfin, nous définissons notre onDestroy() .

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

Android Étape 2: Demande de serveur asynchrone

L'exemple de code complet pour cette application (serveur Android + Node) est disponible dans le référentiel Github de PayPal Developer .

À ce stade, le bouton PayPal des paiements futurs a été cliqué, nous avons un code d’authentification et un identifiant de métadonnées du kit de développement PayPal, et nous devons les transmettre à notre serveur pour terminer le processus de paiement futur.

En arrière-plan, nous faisons quelques choses:

  • Nous avons configuré l'URI pour que notre serveur soit http://10.0.2.2:3000/fpstore , qui /fpstore noeud final /fpstore de notre serveur s'exécutant sur localhost.
  • L'objet JSON qui sera envoyé via est alors configuré, qui contient le code d'authentification et l'ID de métadonnées.
  • La connexion est alors faite. En cas de demande réussie (plage 200/201), nous pouvons attendre une réponse du serveur. Nous lisons cette réponse puis la renvoyons.
  • Enfin, nous avons une onPostExecute(...) configurée pour gérer cette chaîne de serveur renvoyée. Dans le cas de cet exemple, il est simplement connecté.
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);
    }
}

Etape 3 d'Android: Serveur de noeud pour obtenir le paiement de jeton et de processus d'accès

L'exemple de code complet pour cette application (serveur Android + Node) est disponible dans le référentiel Github de PayPal Developer .

A partir de l'étape 2, une requête asynchrone a été effectuée sur notre serveur au niveau du /fpstore final /fpstore , en transmettant le code d'authentification et l'ID de métadonnées. Nous devons maintenant les échanger contre un jeton pour compléter la demande et traiter le paiement futur.

Tout d'abord, nous configurons nos variables de configuration et notre objet.

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());

Nous établissons maintenant un itinéraire Express qui écoutera les requêtes POST envoyées au point de terminaison /fpstore partir de notre code Android.

Nous faisons un certain nombre de choses dans cette voie:

  • Nous capturons le code d'authentification et l'ID de métadonnées du corps POST.
  • Nous faisons ensuite une demande à generateToken() , en passant par l'objet code. En cas de succès, nous obtenons un jeton pouvant être utilisé pour créer le paiement.
  • Ensuite, les objets de configuration sont créés pour le paiement futur à effectuer et une demande de payment.create(...) est transmise, transmettant les futurs objets de configuration de paiement et de paiement. Cela crée le paiement futur.
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));
                }
            });
        }
    });
});

Enfin, nous créons le serveur pour écouter sur le port 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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow