Sök…


Anmärkningar

Detta exempel visar ett praktiskt exempel på slutet till slut på att skapa en framtida PayPal-betalning från en Android-enhet med en Node-server.

Android Steg 1: Layout, initiering och hantering av serverrespons

Den fullständiga provkoden för den här applikationen (Android + Node-server) är tillgänglig i PayPal Developer Github-arkivet .

Det första steget i att skapa Android-delen av vår applikation är att skapa en grundläggande layout och hantera svar som kommer tillbaka från servern som vi ställer in i Node.

Börja med att skapa ett nytt PayPalConfiguration-objekt för att hysa din applikationsinformation.

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

Därefter lägger vi till en enkel knapp till onCreate(...) att fungera som vår betalningsinitiering. Detta är helt enkelt för att utlösa åtgärden och bör placeras som initieringsprocessen för att skapa en framtida betalning för en användare (t.ex. när de går med på ett prenumeration).

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

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

Under res > layout > activity_main.xml lägger vi till definitionen för knappen med tillhörande åtgärd, när man beginFuturePayment(...) den beginFuturePayment(...) , som vi definierar på en minut.

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

Under res > values > strings.xml vi sedan till en strängreferens för knappen.

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

Nu lägger vi till knapphanteraren för att initiera samtalet för att starta den framtida betalningsprocessen när användaren klickar på knappen. Det vi gör här är att starta betalningstjänsten med det konfigurationsobjekt som vi satt upp högst upp i detta exempel.

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

När det samtalet för att göra en framtida betalning inleds kommer vi att få viss information som måste skickas till vår server. Vi extraherar den här informationen från den giltiga framtida betalningsbegäran ( authCode och metadataId ) och kör sedan async-begäran till servern för att slutföra den framtida betalningen (beskrivs i steg 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");
    }
}

Slutligen definierar vi vår onDestroy() .

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

Android Steg 2: Async Server Request

Den fullständiga provkoden för den här applikationen (Android + Node-server) är tillgänglig i PayPal Developer Github-arkivet .

Vid denna tidpunkt har knappen för framtida betalningar för PayPal klickats, vi har en autorisationskod och metadata-ID från PayPal SDK, och vi måste vidarebefordra dem till vår server för att slutföra den framtida betalningsprocessen.

I bakgrundsprocessen nedan gör vi några saker:

  • Vi skapade URI för att vår server ska vara http://10.0.2.2:3000/fpstore , vilket träffar /fpstore slutpunkt för vår server som körs på localhost.
  • JSON-objektet som kommer att skickas in skapas sedan, som innehåller autorisationskoden och metadata-ID.
  • Anslutningen görs sedan. Vid en framgångsrik begäran (200/201-intervall) kan vi förvänta oss ett svar tillbaka från servern. Vi läser det svaret och returnerar sedan det.
  • Slutligen har vi en onPostExecute(...) -metod inställd för att hantera den returnerade serversträngen. I det här exemplet loggas det helt enkelt.
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);
    }
}

Android Steg 3: Nodserver för att få åtkomsttoken och bearbeta betalning

Den fullständiga provkoden för den här applikationen (Android + Node-server) är tillgänglig i PayPal Developer Github-arkivet .

Från steg 2 har en async-begäran gjorts till vår server vid /fpstore slutpunkten och passerar ID-koden och metadata-ID. Vi måste nu byta ut dem mot ett symbol för att slutföra begäran och behandla den framtida betalningen.

Först ställer vi in våra konfigurationsvariabler och objekt.

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

Nu skapar vi en Express-rutt som lyssnar på POST-förfrågningar som skickas till /fpstore slutpunkt från vår Android-kod.

Vi gör ett antal saker på den här vägen:

  • Vi fångar autorisationskoden och metadata-ID från POST-organet.
  • Vi gör sedan en begäran om att generateToken() och passerar kodobjektet. Om det lyckas får vi ett symbol som kan användas för att skapa betalningen.
  • Därefter skapas konfigurationsobjekten för den framtida betalningen som ska göras, och en begäran till payment.create(...) görs och passerar framtida betalnings- och betalningskonfigurationsobjekt. Detta skapar den framtida betalningen.
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));
                }
            });
        }
    });
});

Slutligen skapar vi servern för att lyssna på 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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow