В этом уроке я покажу, как разрешить пользователям покупать товары или услуги из вашего приложения с помощью Stripe . Stripe — это один из самых простых способов управления вашими онлайн-продуктами, заказами и платежами.
Вы можете найти код для этого урока на Github .
Полоса приборной панели
В конце этого руководства пользователи смогут покупать подписки на планы. Первый шаг — создание простых планов.
Для начала войдите в Stripe (или создайте аккаунт, если вы этого еще не сделали). Убедитесь, что вы находитесь в тестовом режиме, прежде чем создавать планы на приборной панели .
Ниже я создал 3 плана подписки: еженедельно , ежемесячно и ежегодно . У них есть некоторая объемная информация и цены, которые нужно отличать друг от друга.
Настройка проекта Android
Создайте новый проект в Android Studio и добавьте эти строки в зависимости в файле build.gradle :
compile ('com.stripe:stripe-android:1.0.4@aar'){
transitive=true
}
Поскольку этому приложению потребуется подключение к Интернету, добавьте следующее разрешение пользователя в файл AndroidManifest.xml :
<uses-permission android:name="android.permission.INTERNET" />
Загрузка продуктов
Чтобы загрузить наши планы с информационной панели Stripe, нам сначала нужно подключить наше приложение к нему с помощью API-ключей .
Всего 4 ключа, но мы собираемся использовать только тестовые ключи. Теперь откройте MainActivity.class и добавьте эти объявления перед onCreate()
ArrayList<SimplePlan> planArrayList;
RecyclerView recyclerView;
ItemsAdapter adapter;
Затем внутри onCreate()
ArrayList :
planArrayList = new ArrayList<>();
new Async().execute();
Внутри класса Main нам нужно создать AysncTask
Эта задача загрузит данные с чередования и будет запущена в новом потоке, поэтому основной поток не будет нарушен событиями сетевого подключения.
Добавьте этот класс в основной код активности:
public class Async extends AsyncTask<Void,String,ArrayList<SimplePlan>> {
@Override
protected ArrayList<SimplePlan> doInBackground(Void... params) {
try {
String line, newjson = "";
URL url = new URL("[YOUR_SERVER_PLANS_SCRIPT_URL]");
try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"))) {
while ((line = reader.readLine()) != null) {
newjson += line;
}
String json = newjson.toString();
JSONObject jObj = new JSONObject(json);
Log.e("Obj",jObj.toString());
JSONArray plans = jObj.getJSONArray("plans");
for (int i=0;i<plans.length();i++){
JSONObject plan = plans.getJSONObject(i);
plan.getString("amount");
Log.e("Amount",plan.getString("amount"));
planArrayList.add(new SimplePlan(plan.getInt("amount"),plan.getString("name"),plan.getString("statement_descriptor")));
}
}
} catch (Exception e) {
e.printStackTrace();
}
return planArrayList;
}
@Override
protected void onPostExecute(final ArrayList<SimplePlan> plan) {
super.onPostExecute(plan);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
showRcv(plan);
}
},3000);
}
}
Этот код извлекает все планы из API Stripe и добавляет их в ArrayList с именем planArrayList . Все эти инструкции выполняются в фоновом режиме . Эта функция doInBackground
Другая функция onPostExecute(final ArrayList<SimplePlan> plans)
В качестве параметра требуется тот же ArrayList, который возвращается из первого метода. Поскольку мы не совсем уверены, сколько может длиться первый вызов в секундах, лучше запустить второй метод через определенный промежуток времени, после которого мы уверены, что вызов завершен. Этот период составляет 3000 мс .
По истечении этого времени эта функция запускает еще одну, которая называется showRcv(plans)
Вы можете найти его код ниже:
public void showRcv(ArrayList<SimplePlan> plans){
adapter = new ItemsAdapter(this,plans);
recyclerView = (RecyclerView)findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
}
До сих пор мы просто перечисляем планы внутри приложения. Я не буду фокусироваться на адаптере RecyclerView и коде ViewHolder, но вы можете найти их в Github .
Вот как будут перечислены планы:
Каждый элемент, указанный в основном упражнении, имеет кнопку « Купить» справа.
На каждой кнопке покупки есть OnClickListener :
holder.buy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent buyIntent = new Intent(activity,PayActivity.class);
buyIntent.putExtra("plan_id",""+planArrayList.get(i).getId());
buyIntent.putExtra("plan_price",planArrayList.get(i).getAmount());
buyIntent.putExtra("plan_name",""+planArrayList.get(i).getName());
activity.startActivity(buyIntent);
}
});
При нажатии кнопки две переменные передаются как дополнительные функции : plan_price и plan_name . Это самые важные для создания заряда.
Прием платежей
Щелкните правой кнопкой мыши на каталоге вашего пакета и создайте новое пустое действие . Это действие откроется после того, как любой из планов будет выбран для покупки.
Его код xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.theodhor.stripeandroid.PayActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/cardNumber"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:text="4242 4242 4242 4242" />
<EditText
android:layout_width="30dp"
android:layout_height="wrap_content"
android:inputType="number"
android:ems="10"
android:id="@+id/month"
android:layout_below="@+id/cardNumber"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:text="12" />
<EditText
android:layout_width="30dp"
android:layout_height="wrap_content"
android:inputType="number"
android:ems="10"
android:id="@+id/year"
android:text="19"
android:layout_below="@+id/cardNumber"
android:layout_toRightOf="@+id/textView"
android:layout_toEndOf="@+id/textView" />
<TextView
android:layout_width="wrap_content"
android:layout_height="36dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="/"
android:id="@+id/textView"
android:layout_alignBottom="@+id/month"
android:layout_toRightOf="@+id/month"
android:layout_toEndOf="@+id/month" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/cvc"
android:text="123"
android:layout_below="@+id/cardNumber"
android:layout_toRightOf="@+id/year"
android:layout_toEndOf="@+id/year"
android:layout_marginLeft="49dp"
android:layout_marginStart="49dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Submit"
android:id="@+id/submitButton"
android:layout_below="@+id/cvc"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:onClick="submitCard" />
</RelativeLayout>
</RelativeLayout>
Платная деятельность
Нам нужно объявить некоторые переменные внутри этого класса.
Stripe stripe;
Integer amount;
String name;
Card card;
Token tok;
Теперь внутри onCreate()
Buy ранее. Сумма и имя цены плана будут использованы позже, когда будет создан сбор.
Bundle extras = getIntent().getExtras();
amount = extras.getInt("plan_price");
name = extras.getString("plan_name");
Also, a Stripe instance will be created using the *Publishable Test Key*:
try {
stripe = new Stripe("[YOUR_PK_TEST_KEY_HERE]");
} catch (AuthenticationException e) {
e.printStackTrace();
}
Перед созданием платежа информация Карты должна быть проверена.
Этот метод sumbitCard(View view)
токен карты, который будет использоваться для оплаты.
public void submitCard(View view) {
// TODO: replace with your own test key
TextView cardNumberField = (TextView) findViewById(R.id.cardNumber);
TextView monthField = (TextView) findViewById(R.id.month);
TextView yearField = (TextView) findViewById(R.id.year);
TextView cvcField = (TextView) findViewById(R.id.cvc);
card = new Card(
cardNumberField.getText().toString(),
Integer.valueOf(monthField.getText().toString()),
Integer.valueOf(yearField.getText().toString()),
cvcField.getText().toString()
);
card.setCurrency("usd");
card.setName("[NAME_SURNAME]");
card.setAddressZip("[ZIP]");
/*
card.setNumber("4242424242424242");
card.setExpMonth(12);
card.setExpYear(19);
card.setCVC("123");
*/
stripe.createToken(card, "[YOUR_PK_TEST_KEY_HERE]", new TokenCallback() {
public void onSuccess(Token token) {
// TODO: Send Token information to your backend to initiate a charge
Toast.makeText(getApplicationContext(), "Token created: " + token.getId(), Toast.LENGTH_LONG).show();
tok = token;
new StripeCharge(token.getId()).execute();
}
public void onError(Exception error) {
Log.d("Stripe", error.getLocalizedMessage());
}
});
Информация о тестировании по умолчанию для действительной карты показана ниже:
но вы можете установить значения с помощью:
card.setNumber("4242424242424242");
card.setExpMonth(12);
card.setExpYear(19);
card.setCVC("123");
Таким образом, после проверки карты и генерирования токена можно создать заряд. Заряд создается вашим серверным скриптом charge.php
Поэтому нам нужно отправить данные на сервер, включая токен проверки карты , и они не должны выполняться в главном потоке .
Внутри PayActivity.class создайте новый класс AsyncTask с именем StripeCharge :
public class StripeCharge extends AsyncTask<String, Void, String> {
String token;
public StripeCharge(String token) {
this.token = token;
}
@Override
protected String doInBackground(String... params) {
new Thread() {
@Override
public void run() {
postData(name,token,""+amount);
}
}.start();
return "Done";
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.e("Result",s);
}
}
Наиболее важными параметрами модели оплаты являются сумма , валюта и карта, идентифицируемая идентификатором токена .
Следующий метод выполняет вызов на сервер, публикуя необходимые данные для создания платы:
public void postData(String description, String token,String amount) {
// Create a new HttpClient and Post Header
try {
URL url = new URL("[YOUR_SERVER_CHARGE_SCRIPT_URL]");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new NameValuePair("method", "charge"));
params.add(new NameValuePair("description", description));
params.add(new NameValuePair("source", token));
params.add(new NameValuePair("amount", amount));
OutputStream os = null;
os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
writer.write(getQuery(params));
writer.flush();
writer.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Если зарядка прошла успешно, вы должны увидеть сумму, переведенную в общий объем Stripe Dashboard, как показано ниже:
Серверный скрипт (PHP)
Быть осторожен! Ваш секретный ключ API должен существовать только в ваших серверных сценариях. В целях безопасности не включайте его в код на стороне клиента.
retrieveplans.php
<?php
define('STRIPE_SECRET_KEY','[YOUR_SECRET_API_KEY]');
define('STRIPE_PUBLIC_KEY','[YOUR_PUBLISHEABLE_API_KEY]');
header('Content-Type: application/json');
$results = array();
require 'vendor/autoload.php';
\Stripe\Stripe::setApiKey(STRIPE_SECRET_KEY);
try{
$products = \Stripe\Plan::all();
$results['response'] = "Success";
$results['plans'] = $products->data;
}catch (Exception $e){
$results['response'] = "Error";
$results['plans'] = $e->getMessage();
}
echo json_encode($results);
и другой сценарий, который использует token id
amount
платы .
charge.php
<?php
define('STRIPE_SECRET_KEY','[YOUR_SECRET_API_KEY]');
define('STRIPE_PUBLIC_KEY','[YOUR_PUBLISHEABLE_API_KEY]');
header('Content-Type: application/json');
$results = array();
require 'vendor/autoload.php';
\Stripe\Stripe::setApiKey(STRIPE_SECRET_KEY);
if(isset($_POST['method'])){
$method = $_POST['method'];
if($method =="charge"){
$amount = $_POST['amount'];
$currency = $_POST['currency'];
$source = $_POST['source'];
$description = $_POST['description'];
try {
$charge = \Stripe\Charge::create(array(
"amount" => $amount, // Amount in cents
"currency" => $currency,
"source" => $source,
"description" => $description
));
if($charge!=null){
$results['response'] = "Success";
$results['message'] = "Charge has been completed";
}
} catch(\Stripe\Error\Card $e) {
$results['response'] = "Error";
$results['message'] = $e->getMessage();
}
echo json_encode($results);
}else {
$results['response'] = "Error";
$results['messsage'] = "Method name is not correct";
echo json_encode($results);
}
}else {
$results['response'] = "Error";
$results['message'] = "No method has been set";
echo json_encode($results);
}
Вывод
Stripe — одна из лучших платформ онлайн-платежей. Его уникальная панель инструментов позволяет создавать приложения для электронной коммерции и продавать продукты даже без единой строки внутреннего кода.
Я надеюсь, что вы найдете его таким же простым в использовании, как и я, и если у вас есть какие-либо комментарии или вопросы, пожалуйста, дайте мне знать ниже.