Stripe:处理 charge/customer 错误,然后将数据插入 PHP 中的数据库
Stripe : handling charge/customer errors then insert data into DB in PHP
我正在使用 Silex 中的 Stripe。在这里,在我的路线中,我从表单获取数据,然后我想创建一个 $customer
和一个 $charge
对象,然后我想将客户和订单信息保存到我的数据库中。
我还想按照 Stripe 文档中的建议使用 try/catch 捕获所有可能的错误,但我觉得我的 try/catch 太长了。如果尝试成功,我想将数据插入我的数据库,但我不知道什么是最佳实践。
这是我的代码:
$app->post('/{category}/{id}', function ($id) use ($app) {
$message = null;
$book = $app['dao.book']->findById($id);
$minAmount = $book->getPrice();
$paidAmount = floatval($_POST['amount']);
// check if value matches
$convMinAmount = ($book->getPrice()) * 100;
$convPaidAmount = (floatval($_POST['amount'])) * 100;
if (($convMinAmount > $convPaidAmount)) {
$message = 'Veuillez saisir un montant plus élevé que le montant minimum s\'il vous plait.';
} else {
$item_bought = $book->getTitle();
$token = $_POST['stripeToken'];
$stripeinfo = \Stripe\Token::retrieve($token);
$email = $stripeinfo->email;
$customer = \Stripe\Customer::create(array(
'email' => $email,
'source' => $token
));
try {
$charge = \Stripe\Charge::create(array(
'customer' => $customer->id,
'amount' => $paidAmount * 100,
'currency' => "eur",
'description' => 'Achat d\'un livre',
'receipt_email' => $customer->email
));
// Prepare values for insert into DB
$full_name = $charge->source->name;
$address = $charge->source->address_line1 . ', ' . $charge->source->address_city .
' ' . $charge->source->address_zip . ', ' . $charge->source->address_country;
// Save order to DB
$commande = new Commande();
$commande->setName($full_name);
$commande->setAdress($address);
$commande->setItemBought($item_bought);
$commande->setPricePaid($paidAmount);
$commande->setEmail($email);
$app['dao.commande']->save($commande);
$message = 'Merci pour votre achat. Votre commande d\'un montant de ' . (floatval($charge->amount)) / 100 . '€ est validée. Un mail récapitulatif vous a été envoyé.';
} catch (\Stripe\Error\Card $e) {
echo($e->getMessage());
// Since it's a decline, \Stripe\Error\Card will be caught
$body = $e->getJsonBody();
$err = $body['error'];
$message = $err;
} catch (\Stripe\Error\RateLimit $e) {
// Too many requests made to the API too quickly
$message = 'Too many requests, veuillez réessayer plus tard s\'il vous plait.';
} catch (\Stripe\Error\InvalidRequest $e) {
// Invalid parameters were supplied to Stripe's API
print('Status is: ' . $e->getHttpStatus() . "\n");
$message = 'Les paramètres sont invalides, veuillez s\'il vous plait contacter le webmaster du site.';
} catch (\Stripe\Error\Authentication $e) {
// Authentication with Stripe's API failed
// (maybe you changed API keys recently)
$message = 'L\'authentication à l\'API Stripe a échoué, veuillez s\'il vous plait contacter le webmaster du site.';
} catch (\Stripe\Error\ApiConnection $e) {
// Network communication with Stripe failed
$message = 'La communication a échoué, veuillez réessayer plus tard s\'il vous plait.';
} catch (\Stripe\Error\Base $e) {
// Display a very generic error to the user, and maybe send
// yourself an email
$message = 'Il semblerait que la requête ait échoué, veuillez réessayer plus tard s\'il vous plait';
} catch (Exception $e) {
// Something else happened, completely unrelated to Stripe
$message = 'Il semblerait que la requête ait échoué, veuillez réessayer plus tard s\'il vous plait';
}
}
return $app['twig']->render('book.html.twig', array(
'book' => $book,
'message' => $message,
'minAmount' => $minAmount
));
最后,我 return $message
处理任何情况,并将用户重定向到书页。
抱歉这个菜鸟问题,我在这里迷路了。该代码正在运行,但我不确定它是最好的方法。感谢您的帮助。
我没用过silex,不过应该和Symfony有很多共同点。在 symfony 中你可以使用事件监听器。 Here 您可以查看一些有关如何实现事件侦听器的示例。
想法是监听异常事件。检查异常是否来自 Stripe,并根据需要设置消息。基本上,您只需将此代码移至事件侦听器,这样您就可以重用它而无需重复代码。然后你可以像这样修改你的例子:
} catch (\Stripe\ErrorInterface $e) {
$message = $e->getMessage();
} catch (SomeDbException $dbException){
...
}
假设所有 Stripe Errors 异常都实现相同的接口。 (从未使用过条纹)。
我不知道这是否是最佳实践,但它可以减少和清除您的代码。
编辑
对不起,我误解了你的问题。就你的观点。您应该保留它,因为它预计会有一些额外的数据库异常。如果你把它放在 try/catch 块之后,即使有异常,它也会将数据插入数据库。
但最佳做法是将您的代码(持久保存到数据库)提取到不同的服务中。此方法应该只负责获取请求并返回响应。
因此关于事件的第一点可能如下所示:
if (($convMinAmount > $convPaidAmount)) {
$message = 'Veuillez saisir un montant plus élevé que le montant minimum s\'il vous plait.';
} else {
$item_bought = $book->getTitle();
try{
$stripeService->makeRequest($_POST['stripeToken'],...)
$databaseService->insertCommande($charge, $fulname, $address,...)
$message = 'Merci pour votre achat. Votre commande d\'un montant de ' . (floatval($charge->amount)) / 100 . '€ est validée. Un mail récapitulatif vous a été envoyé.';
} catch (\Stripe\ErrorInterface $e) {
$message = $e->getMessage();
}
}
return $app['twig']->render('book.html.twig', array(
'book' => $book,
'message' => $message,
'minAmount' => $minAmount
));
我正在使用 Silex 中的 Stripe。在这里,在我的路线中,我从表单获取数据,然后我想创建一个 $customer
和一个 $charge
对象,然后我想将客户和订单信息保存到我的数据库中。
我还想按照 Stripe 文档中的建议使用 try/catch 捕获所有可能的错误,但我觉得我的 try/catch 太长了。如果尝试成功,我想将数据插入我的数据库,但我不知道什么是最佳实践。
这是我的代码:
$app->post('/{category}/{id}', function ($id) use ($app) {
$message = null;
$book = $app['dao.book']->findById($id);
$minAmount = $book->getPrice();
$paidAmount = floatval($_POST['amount']);
// check if value matches
$convMinAmount = ($book->getPrice()) * 100;
$convPaidAmount = (floatval($_POST['amount'])) * 100;
if (($convMinAmount > $convPaidAmount)) {
$message = 'Veuillez saisir un montant plus élevé que le montant minimum s\'il vous plait.';
} else {
$item_bought = $book->getTitle();
$token = $_POST['stripeToken'];
$stripeinfo = \Stripe\Token::retrieve($token);
$email = $stripeinfo->email;
$customer = \Stripe\Customer::create(array(
'email' => $email,
'source' => $token
));
try {
$charge = \Stripe\Charge::create(array(
'customer' => $customer->id,
'amount' => $paidAmount * 100,
'currency' => "eur",
'description' => 'Achat d\'un livre',
'receipt_email' => $customer->email
));
// Prepare values for insert into DB
$full_name = $charge->source->name;
$address = $charge->source->address_line1 . ', ' . $charge->source->address_city .
' ' . $charge->source->address_zip . ', ' . $charge->source->address_country;
// Save order to DB
$commande = new Commande();
$commande->setName($full_name);
$commande->setAdress($address);
$commande->setItemBought($item_bought);
$commande->setPricePaid($paidAmount);
$commande->setEmail($email);
$app['dao.commande']->save($commande);
$message = 'Merci pour votre achat. Votre commande d\'un montant de ' . (floatval($charge->amount)) / 100 . '€ est validée. Un mail récapitulatif vous a été envoyé.';
} catch (\Stripe\Error\Card $e) {
echo($e->getMessage());
// Since it's a decline, \Stripe\Error\Card will be caught
$body = $e->getJsonBody();
$err = $body['error'];
$message = $err;
} catch (\Stripe\Error\RateLimit $e) {
// Too many requests made to the API too quickly
$message = 'Too many requests, veuillez réessayer plus tard s\'il vous plait.';
} catch (\Stripe\Error\InvalidRequest $e) {
// Invalid parameters were supplied to Stripe's API
print('Status is: ' . $e->getHttpStatus() . "\n");
$message = 'Les paramètres sont invalides, veuillez s\'il vous plait contacter le webmaster du site.';
} catch (\Stripe\Error\Authentication $e) {
// Authentication with Stripe's API failed
// (maybe you changed API keys recently)
$message = 'L\'authentication à l\'API Stripe a échoué, veuillez s\'il vous plait contacter le webmaster du site.';
} catch (\Stripe\Error\ApiConnection $e) {
// Network communication with Stripe failed
$message = 'La communication a échoué, veuillez réessayer plus tard s\'il vous plait.';
} catch (\Stripe\Error\Base $e) {
// Display a very generic error to the user, and maybe send
// yourself an email
$message = 'Il semblerait que la requête ait échoué, veuillez réessayer plus tard s\'il vous plait';
} catch (Exception $e) {
// Something else happened, completely unrelated to Stripe
$message = 'Il semblerait que la requête ait échoué, veuillez réessayer plus tard s\'il vous plait';
}
}
return $app['twig']->render('book.html.twig', array(
'book' => $book,
'message' => $message,
'minAmount' => $minAmount
));
最后,我 return $message
处理任何情况,并将用户重定向到书页。
抱歉这个菜鸟问题,我在这里迷路了。该代码正在运行,但我不确定它是最好的方法。感谢您的帮助。
我没用过silex,不过应该和Symfony有很多共同点。在 symfony 中你可以使用事件监听器。 Here 您可以查看一些有关如何实现事件侦听器的示例。
想法是监听异常事件。检查异常是否来自 Stripe,并根据需要设置消息。基本上,您只需将此代码移至事件侦听器,这样您就可以重用它而无需重复代码。然后你可以像这样修改你的例子:
} catch (\Stripe\ErrorInterface $e) {
$message = $e->getMessage();
} catch (SomeDbException $dbException){
...
}
假设所有 Stripe Errors 异常都实现相同的接口。 (从未使用过条纹)。
我不知道这是否是最佳实践,但它可以减少和清除您的代码。
编辑 对不起,我误解了你的问题。就你的观点。您应该保留它,因为它预计会有一些额外的数据库异常。如果你把它放在 try/catch 块之后,即使有异常,它也会将数据插入数据库。
但最佳做法是将您的代码(持久保存到数据库)提取到不同的服务中。此方法应该只负责获取请求并返回响应。
因此关于事件的第一点可能如下所示:
if (($convMinAmount > $convPaidAmount)) {
$message = 'Veuillez saisir un montant plus élevé que le montant minimum s\'il vous plait.';
} else {
$item_bought = $book->getTitle();
try{
$stripeService->makeRequest($_POST['stripeToken'],...)
$databaseService->insertCommande($charge, $fulname, $address,...)
$message = 'Merci pour votre achat. Votre commande d\'un montant de ' . (floatval($charge->amount)) / 100 . '€ est validée. Un mail récapitulatif vous a été envoyé.';
} catch (\Stripe\ErrorInterface $e) {
$message = $e->getMessage();
}
}
return $app['twig']->render('book.html.twig', array(
'book' => $book,
'message' => $message,
'minAmount' => $minAmount
));