里面有很多信息!
我知道有很多线程正在讨论这个问题,但是没有正确的答案,Stripe自己的教程和参考资料要好得多。所以希望我(以及其他人)可以最终看到这个长期存在的问题,为我们的业余爱好者开发。
我一直在努力实施Stripe的API超过两周,仍然遇到同样的问题。我的Android代码正常工作,直到我从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脚本的安全连接,它应该处理其余的。
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);
}
此DB任务的PHP脚本:
<?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之间,它似乎出错了,因为我从来没有得到任何回报,除了我的控制台中的一个巨大的ERROR消息。
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: <com.stripe.android.model.Token@... id=> JSON: { from API request 'req_...'
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "card": {
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "address_city": null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "address_country": null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "address_line1": null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "address_line2": null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "address_state": null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "address_zip": null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "country": "US",
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "currency": null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "cvc": null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "exp_month": 12,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "exp_year": 2019,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "fingerprint": null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "last4": "4242",
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "name": null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "number": null,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "type": null
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: },
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "created": "Aug 23, 2016 16:04:25",
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "id": "tok_...",
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "livemode": false,
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: "used": 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->handleApiError('{\n "error": {\n...', 400, Array, Array)
08-23 16:04:28.083 20867-20867/... E/DatabaseTask: #1 /home/.../Stripe/lib/ApiRequestor.php(65): Stripe\ApiRequestor->_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: <com.stripe.android.model.Token@... id=> JSON: { from API request 'req_...' "card": { "address_city": null, "address_country": null, "address_line1": null, "address_line2": null, "address_state": null, "address_zip": null, "country": "US", "currency": null, "cvc": null, "exp_month": 12, "exp_year": 2019, "fingerprint": null, "last4": "4242", "name": null, "number": null, "type": null }, "created": "Aug 23, 2016 16:04:25", "id": "tok_...", "livemode": false, "used": false}' in /home/.../Stripe/lib/ApiRequestor.php:108Stack trace:#0 /home/.../Stripe/lib/ApiRequestor.php(227): Stripe\ApiRequestor->handleApiError('{\n "error": {\n...', 400, Array, Array)#1 /home/.../Stripe/lib/ApiRequestor.php(65): Stripe\ApiRequestor->_interpretRe in <b>/home/.../Stripe/lib/ApiRequestor.php</b> on line <b>108</b><br />
(链接,ID,令牌和其他个人内容被替换为......)
所以我已经尝试了几乎所有我能在网上找到的关于“没有这样的令牌:”的信息,但无济于事。
我检查了什么: - 我的钥匙都没问题,这里没有错配 - 我的应用程序和我的PHP脚本之间有正确的连接 - 令牌已正确创建并由Stripe验证 - 我的服务器具有付费SSL证书,并与HttpsURLConnection建立了安全连接
我尝试了什么: - 一遍又一遍刷新钥匙 - 在POST方法中将我的令牌作为字符串发送 - 尝试将我的令牌作为JSONtoken发送(从未让它工作)&gt; Passing Stripe tokens to server and handling on server - 在asyncTask之外使用POST方法(读取它不需要) - 反复阅读Stripe的整个文档&gt; https://stripe.com/docs/mobile/android - 一遍又一遍地反复示例项目&gt; https://github.com/stripe/stripe-android/tree/master/example - 搜索视频教程,但只找到了在网站上集成的教程 - 搜索在线课程,仅用于网络集成
所以现在我真的想知道Stripe对这个不可能完成的任务意味着什么:
在服务器上设置可以接收HTTP POST呼叫的端点 为了令牌。在onActivityResult方法(适用于Android Pay)或 onSuccess回调(使用自己的表单时),你需要POST 提供令牌到您的服务器。确保与您的任何沟通 服务器受SSL保护,以防止窃听。
如果您需要更多信息,请不要犹豫,因为这是完成我的第一次正确申请的最后一步。另外,请记住,过去3年我已经通过追踪和错误收集了所有的知识,尽管我知道很多事情,但我可能会错过一些基本知识。
感谢。
答案 0 :(得分:3)
这里的错误是,您传递了从Stripe的SDK返回的整个令牌对象,而不是传递令牌ID tok_XXX
。然后请求失败并显示错误
未捕获的异常&#39; Stripe \ Error \ InvalidRequest&#39;消息&#39;没有这样的标记:&lt; com.stripe.android.model.Token @ ... id =&gt; JSON:{来自API请求&#39; req _...&#39;
您需要更改代码以将令牌ID发送到PHP脚本,以解决问题。
builder.append(URLEncoder.encode(token.getId(), "UTF-8"));