PayPal
Paiements futurs mobiles (application de bout en bout)
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/fpstorenoeud final/fpstorede 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');
});