Поиск…


замечания

В этом примере показан практический пример конца будущего платежа PayPal с Android-устройства с использованием сервера Node.

Android Шаг 1: Макет, инициализация и обработка ответов сервера

Полный образец кода для этого приложения (сервер Android + Node) доступен в репозитории PayPal Developer Github .

Первым этапом создания части приложения Android является настройка базового макета и обработка ответов, возвращаемых с сервера, который мы установим в узле.

Начните с создания нового объекта PayPalConfiguration для размещения информации о вашем приложении.

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

Затем добавим простую кнопку onCreate(...) чтобы действовать как начало платежа. Это просто инициирует действие и должно быть помещено в качестве процесса инициирования для создания будущего платежа для пользователя (например, когда они согласны с подпиской).

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

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

В разделе res > layout > activity_main.xml мы добавим определение для кнопки со связанным с ней действием, при нажатии на нее называется beginFuturePayment(...) , который мы определим через минуту.

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

В разделе res > values > strings.xml мы добавим строчную ссылку для кнопки.

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

Теперь мы добавляем обработчик кнопки, чтобы инициировать вызов, чтобы начать процесс будущих платежей, когда пользователь нажимает кнопку. Что мы делаем здесь, это запуск платежного сервиса с помощью объекта конфигурации, который мы установили в верхней части этого примера.

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

Когда будет инициирован вызов для будущего платежа, нам будет предоставлена ​​некоторая информация, которая должна быть отправлена ​​на наш сервер. Мы извлекаем эту информацию из действительного будущего платежного запроса ( authCode и metadataId ), затем выполняем запрос асинхронного запроса на сервер для завершения будущей оплаты (подробно описанный в шаге 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");
    }
}

Наконец, мы определяем наш onDestroy() .

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

Android Шаг 2: Запрос сервера Async

Полный образец кода для этого приложения (сервер Android + Node) доступен в репозитории PayPal Developer Github .

На этом этапе нажата кнопка будущих платежей PayPal, у нас есть код аутентификации и идентификатор метаданных из SDK PayPal, и нам нужно передать их на наш сервер, чтобы завершить процесс будущих платежей.

В фоновом процессе ниже мы делаем несколько вещей:

  • Мы настроили URI, чтобы для нашего сервера был http://10.0.2.2:3000/fpstore , который попадает в /fpstore точку /fpstore нашего сервера, работающего на localhost.
  • Затем будет создан объект JSON, который будет отправлен через него, который содержит код аутентификации и идентификатор метаданных.
  • Затем соединение будет выполнено. В случае успешного запроса (диапазон 200/201) мы можем ожидать ответа с сервера. Мы читаем этот ответ, а затем возвращаем его.
  • Наконец, у нас есть onPostExecute(...) настроенный для обработки возвращенной строки сервера. В случае этого примера он просто регистрируется.
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 Шаг 3: Сервер узла для получения доступа к токенам и процессинговым платежам

Полный образец кода для этого приложения (сервер Android + Node) доступен в репозитории PayPal Developer Github .

Начиная с шага 2, асинхронный запрос был /fpstore нашему серверу в /fpstore точке /fpstore , передавая код аутентификации и идентификатор метаданных. Теперь нам нужно обменять их на токен, чтобы выполнить запрос и обработать будущий платеж.

Сначала мы настраиваем наши переменные конфигурации и объект.

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

Теперь мы настроили экспресс-маршрут, который будет прослушивать запросы POST, отправленные в /fpstore точку /fpstore из нашего кода Android.

На этом пути мы делаем несколько вещей:

  • Мы фиксируем код аутентификации и идентификатор метаданных из тела POST.
  • Затем мы делаем запрос на generateToken() , проходя через объект кода. В случае успеха мы получаем токен, который можно использовать для создания платежа.
  • Затем создаются объекты конфигурации для будущей оплаты, которая должна быть сделана, и делается запрос на payment.create(...) , проходящий через будущие объекты конфигурации оплаты и оплаты. Это создает будущий платеж.
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));
                }
            });
        }
    });
});

Наконец, мы создаем сервер для прослушивания на порту 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
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow