使用 Android 发送条带令牌的正确方法 [英] the correct way of sending a stripe token with Android

查看:26
本文介绍了使用 Android 发送条带令牌的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

里面有很多信息!

我知道有多个线程正在讨论这个问题,但没有一个得到正确回答,而且 Stripe 自己的教程和参考资料也没有好得多.所以希望我(和其他人)可以最终看到我们业余爱好者在这个长期存在的问题中的曙光.

I am aware there are multiple threads going on about this issue, but non of them are properly answered, and Stripe's own tutorials and references arent much better. so hopefully I (and other) may finaly see the light in this long lasting issue for us hobby developers.

我已经尝试实现 Stripe 的 API 超过 2 周了,但仍然遇到同样的问题.我的 Android 代码运行正常,直到我从 Stripe 收到我的令牌.

I have been trying to implement Stripe's API for over 2 weeks now, still stuck at the same problem. My Android code is properly working up till the point where I receice my Token back from Stripe.

public class Checkout extends AppCompatActivity {

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

    public void submitCard(View view) throws AuthenticationException {


        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 card = new Card(cardNumberField.getText().toString(), Integer.valueOf(monthField.getText().toString()), Integer.valueOf(yearField.getText().toString()), cvcField.getText().toString());
        //Card newCard = new Card("4242 4242 4242 4242", 12, 19, "123");

        Stripe stripe = new Stripe("pk_test_key");
        stripe.createToken(card, new TokenCallback() {
            @Override
            public void onError(Exception error) {
                //Error
                Toast.makeText(getApplicationContext(), error.getLocalizedMessage(), Toast.LENGTH_LONG).show();
            }

            @Override
            public void onSuccess(Token token) {
                //send token to server
                Toast.makeText(getApplicationContext(), "Succesfully created a token", Toast.LENGTH_LONG).show();       // < this toast works, so my token is fine

                DatabaseTask databaseTask = new DatabaseTask("SENDTOKEN", token);
                databaseTask.execute();

            }
        });
    }

}

创建令牌后,我启动 DatabaseTask,然后该任务应该将该令牌发送到我的服务器(货币和金额在 PHP 脚本 atm 中硬编码).该服务器有付费 SSL 证书,我正在创建一个到我的 PHP 脚本的安全连接,该连接应该处理其余部分.

After my token has been created, I start my DatabaseTask which then should send that Token to my server (Currency and Amount are hardcoded in the PHP script atm). This server has a paid SSL certificate, and I am creating a secure connection to my PHP script which should handle the rest.

public class DatabaseTask extends AsyncTask<String, Void, String> {

    String command = "";
    Token token;

    public DatabaseTask(String mCommand, Token mToken){
        command = mCommand;
        token = mToken;
    }

    @Override
    protected String doInBackground(String... strings) {

        String echoData = "";

        if (command.equals("SENDTOKEN")) {
            try {
                URL url = new URL("https://.../StripeConnection.php"); //there is a connection between the code and PHP script. This is tested.
                HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();


                StringBuilder builder = new StringBuilder();
                builder.append(URLEncoder.encode("stripeToken", "UTF-8"));
                builder.append("=");
                builder.append(URLEncoder.encode(token.toString(), "UTF-8"));
                String urlParameters = builder.toString();

                connection.setRequestMethod("POST");
                connection.setDoOutput(true);
                DataOutputStream dStream = new DataOutputStream(connection.getOutputStream());

                dStream.writeBytes(urlParameters);
                dStream.flush();
                dStream.close();

                BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line = "";
                StringBuilder responseOutput = new StringBuilder();

                while ((line = br.readLine()) != null) {
                    Log.e("DatabaseTask", line);
                    responseOutput.append(line);
                }
                br.close();

                echoData = responseOutput.toString();


            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return echoData;
    }

    protected void onPostExecute(String mData){
        Log.e("DatabaseTask", "onPostExecute result: " + mData);
    }

这个数据库任务的 PHP 脚本:

The PHP script this DB task goes for:

<?php

require_once('Stripe/init.php');

\Stripe\Stripe::setApiKey("sk_test_key");

$token = $_POST['stripeToken'];
$price = $_POST['price'];
$description = $_POST['description'];

// Create the charge on Stripe's servers - this will charge the user's card
try {
  $charge = Stripe\Charge::create(array(
    "amount" => 10000,          //"amount" => $price, in cents. //Hardcoded for testing
    "currency" => "cny",                        //Hardcoded for testing
    "source" => $token,                         //Hardcoded for testing
    "description" => "omschrijving" //"description" => $description //Hardcoded for testing
    ));

    echo "payment went succesfull";
} catch(\Stripe\Error\Card $e) {
  // The card has been declined
  echo "card was declined";
}

?>

似乎在我执行 DatabaseTask 和 PHP 脚本中的第一个 ECHO 之间的某个时间出错了,因为除了控制台中的一个巨大的错误消息之外,我再也没有得到任何回复.

It seems that it goes wrong somewhere between the moment I execute my DatabaseTask, and the first ECHO in the PHP script, as I never get anything back, except for a huge ERROR message in my console.

08-23 16:04:28.083 20867-20867/... E/DatabaseTask: <br />
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: <b>Fatal error</b>:  Uncaught exception 'Stripe\Error\InvalidRequest' with message 'No such token: &lt;com.stripe.android.model.Token@... id=&gt; JSON: { from API request 'req_...'
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:   &quot;card&quot;: {
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;address_city&quot;: null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;address_country&quot;: null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;address_line1&quot;: null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;address_line2&quot;: null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;address_state&quot;: null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;address_zip&quot;: null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;country&quot;: &quot;US&quot;,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;currency&quot;: null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;cvc&quot;: null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;exp_month&quot;: 12,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;exp_year&quot;: 2019,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;fingerprint&quot;: null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;last4&quot;: &quot;4242&quot;,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;name&quot;: null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;number&quot;: null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:     &quot;type&quot;: null
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:   },
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:   &quot;created&quot;: &quot;Aug 23, 2016 16:04:25&quot;,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:   &quot;id&quot;: &quot;tok_...&quot;,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:   &quot;livemode&quot;: false,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask:   &quot;used&quot;: false
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: }' in /home/.../Stripe/lib/ApiRequestor.php:108
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: Stack trace:
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: #0 /home...Stripe/lib/ApiRequestor.php(227): Stripe\ApiRequestor-&gt;handleApiError('{\n  &quot;error&quot;: {\n...', 400, Array, Array)
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: #1 /home/.../Stripe/lib/ApiRequestor.php(65): Stripe\ApiRequestor-&gt;_interpretRe in <b>/home/.../Stripe/lib/ApiRequestor.php</b> on line <b>108</b><br />
08-23 16:04:28.093 20867-20867/... E/Checkout: <br /><b>Fatal error</b>:  Uncaught exception 'Stripe\Error\InvalidRequest' with message 'No such token: &lt;com.stripe.android.model.Token@... id=&gt; JSON: { from API request 'req_...'  &quot;card&quot;: {    &quot;address_city&quot;: null,    &quot;address_country&quot;: null,    &quot;address_line1&quot;: null,    &quot;address_line2&quot;: null,    &quot;address_state&quot;: null,    &quot;address_zip&quot;: null,    &quot;country&quot;: &quot;US&quot;,    &quot;currency&quot;: null,    &quot;cvc&quot;: null,    &quot;exp_month&quot;: 12,    &quot;exp_year&quot;: 2019,    &quot;fingerprint&quot;: null,    &quot;last4&quot;: &quot;4242&quot;,    &quot;name&quot;: null,    &quot;number&quot;: null,    &quot;type&quot;: null  },  &quot;created&quot;: &quot;Aug 23, 2016 16:04:25&quot;,  &quot;id&quot;: &quot;tok_...&quot;,  &quot;livemode&quot;: false,  &quot;used&quot;: false}' in /home/.../Stripe/lib/ApiRequestor.php:108Stack trace:#0 /home/.../Stripe/lib/ApiRequestor.php(227): Stripe\ApiRequestor-&gt;handleApiError('{\n  &quot;error&quot;: {\n...', 400, Array, Array)#1 /home/.../Stripe/lib/ApiRequestor.php(65): Stripe\ApiRequestor-&gt;_interpretRe in <b>/home/.../Stripe/lib/ApiRequestor.php</b> on line <b>108</b><br />

(链接、ID、令牌和其他个人资料被替换为...)

(links, ID's, tokens and other personal stuff is replaced with ...)

因此,我尝试了几乎所有可以在网上找到的有关No such Token:"消息的所有方法,但都无济于事.

So I have tried pretty much everything I could find online about the message "No such Token: ", but to no avail.

我检查了什么:- 我的两把钥匙都没问题,这里没有错配- 我的应用程序和我的 PHP 脚本之间有正确的连接- 令牌已正确创建并由 Stripe 验证- 我的服务器有付费 SSL 证书并与 HttpsURLConnection 建立了安全连接

What did I check: - Both my keys are ok, no missmatch here - There is a proper connection between my app and my PHP script - The token is created properly and verified by Stripe - My server has a paid SSL certificate and made a secure connection with HttpsURLConnection

我尝试了什么:- 一遍又一遍地刷新键- 在 POST 方法中将我的令牌作为字符串发送- 尝试将我的令牌作为 JSONtoken 发送(从来没有让它工作)> 将 Stripe 令牌传递给服务器并在服务器上处理- 在 asyncTask 之外使用 POST 方法(阅读它不需要)- 一遍又一遍地重新阅读 Stripe 的整个文档 > https://stripe.com/docs/手机/安卓- 一遍又一遍地剖析示例项目 > https://github.com/条纹/条纹-android/tree/master/example- 搜索了视频教程,但只找到了网站集成教程- 搜索在线课程,再次仅用于网络集成

What have I tried: - refreshed the keys over and over again - sending my token as a string in a POST method - tried sending my token as a JSONtoken (never got it to work) > Passing Stripe tokens to server and handling on server - took the POST method outside the asyncTask (read that it wasnt needed) - re-read the entire documentation of Stripe over and over again > https://stripe.com/docs/mobile/android - discected the example project over and over again > https://github.com/stripe/stripe-android/tree/master/example - searched for video tutorials, but only found tutorials for integration on websites - searched for online courses, again only for web integration

所以现在我真的很想知道 Stripe 对这个看似不可能完成的任务意味着什么:

So now I really wanna know what Stripe means with this seamingly impossible task:

在您的服务器上设置一个可以接收 HTTP POST 调用的端点为令牌.在 onActivityResult 方法(对于 Android Pay)或onSuccess 回调(使用您自己的表单时),您需要发布向您的服务器提供令牌.确保与您的任何沟通服务器采用 SSL 保护,以防止窃听.

Set up an endpoint on your server that can receive an HTTP POST call for the token. In the onActivityResult method (for Android Pay) or the onSuccess callback (when using your own form), you’ll need to POST the supplied token to your server. Make sure any communication with your server is SSL secured to prevent eavesdropping.

如果您需要更多信息,请不要犹豫,因为这是我完成第一个正确申请的最后一步.另外,请记住,我在过去 3 年里通过错误和错误收集了我的所有知识,即使我知道很多东西,我也可能会错过一些基础知识.

If you need any more information, please dont hesitate to ask, because this is the last step to finishing my first proper application. Also, please keep in mind that I have gathered all my knowledge over the past 3 years by trail and error, and even though I know quite some things, I might miss out on some basic knowledge.

谢谢.

推荐答案

这里的错误是,不是传递令牌 ID tok_XXX,而是传递了从 Stripe 的 SDK 返回的整个 Token 对象.然后请求失败并显示错误

The error here is that instead of passing the token id tok_XXX you pass the entire Token object you got back from Stripe's SDK. The request then fails with the error

未捕获的异常 'Stripe\Error\InvalidRequest' 带有消息 'No such token: <com.stripe.android.model.Token@... id=>JSON:{来自 API 请求 'req_...'

Uncaught exception 'Stripe\Error\InvalidRequest' with message 'No such token: <com.stripe.android.model.Token@... id=> JSON: { from API request 'req_...'

您需要更改代码以将令牌 ID 发送到您的 PHP 脚本,这应该可以解决问题.

You need to change your code to send the token id instead to your PHP script which should fix the issue.

builder.append(URLEncoder.encode(token.getId(), "UTF-8"));

这篇关于使用 Android 发送条带令牌的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆