phcorp / payment-sips-bundle
提供访问 ATOS SIPS 解决方案的支付包
Requires
- php: >=5.3.2
- jms/payment-core-bundle: ~1.0
- psr/log: ~1.0
Requires (Dev)
This package is auto-updated.
Last update: 2024-09-29 04:48:49 UTC
README
KptivePaymentSipsBundle
通过 JMSPaymentCoreBundle 提供对 Atos Worldline SIPS 支付解决方案的访问。
以下支付服务由 Atos SIPS 提供
- Merc@net (BNP Parisbas)
- Cyberplus (Banque Populaire)
- Elys Net (HSBC)
- Scellius (La Banque Postale)
- SogenActif (Société Générale)
- Webaffaires (Crédit du Nord)
- Sherlocks (LCL)
- Citelis (Crédit Mutuel)
- ...
这意味着这个包应该可以与它们中的任何一个无缝工作。
安装
步骤 1
运行
$ php composer.phar require kptive/payment-sips-bundle
或者在你更新供应商之前将以下内容添加到你的 composer.json
{ "require": { "kptive/payment-sips-bundle": "*@dev" } }
步骤 2
在 AppKernel
类中注册这个包。你还需要注册 JMSPaymentCoreBundle
并进行配置。
<?php // app/AppKernel.php public function registerBundles() { $bundles = array( // ... new JMS\Payment\CoreBundle\JMSPaymentCoreBundle(), new Kptive\PaymentSipsBundle\KptivePaymentSipsBundle(), ); // ... } // ...
步骤 3
将你的 SIPS 文件夹内容复制到 app/sips/
。如果你想放在其他地方,只需编辑 pathfile
和二进制位置配置值(见下文)。
你还需要根据你在 pathfile
中指定的内容将你自己的标志图像复制到正确的位置。
配置
kptive_payment_sips: config: merchant_id: "082584341411111" merchant_country: fr normal_return_url: %base_url%/checkout/complete cancel_return_url: %base_url%/checkout/cancel automatic_response_url: %base_url%/checkout/notification pathfile: %kernel.root_dir%/config/sips/param/pathfile currency_code: 978 bin: request_bin: %kernel.root_dir%/config/sips/bin/static/request response_bin: %kernel.root_dir%/config/sips/bin/static/response
用法
假设你有一个 AcmePaymentBundle
,并且你用 Acme\PaymentBundle\Entity\Order
类处理你的订单
<?php namespace Acme\PaymentBundle\Entity; use Doctrine\ORM\Mapping as ORM; use JMS\Payment\CoreBundle\Entity\PaymentInstruction; /** * @ORM\Table(name="acme_order") */ class Order { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\OneToOne(targetEntity="JMS\Payment\CoreBundle\Entity\PaymentInstruction") */ private $paymentInstruction; /** * @ORM\Column(type="decimal", precision=10, scale=2) */ private $amount; /** * @ORM\Column(type="datetime", name="payed_at", nullable=true) */ private $payedAt; // ... public function getId() { return $this->id; } public function getAmount() { return $this->amount; } public function getPaymentInstruction() { return $this->paymentInstruction; } public function setPaymentInstruction(PaymentInstruction $instruction) { $this->paymentInstruction = $instruction; return $this; } public function getPayedAt() { return $this->payedAt; } public function setPayedAt($payedAt) { $this->payedAt = $payedAt; return $this; }
创建一个控制器,带有 details
动作。这是客户可以查看并确认订单的地方。
<?php namespace Acme\PaymentBundle\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use JMS\Payment\CoreBundle\Entity\PaymentInstruction; use Acme\PaymentBundle\Entity\Order; /** * @Route("/checkout") */ class CheckoutController extends Controller { // ... /** * @Route("/details/{id}", name = "payment_details") * @Template() */ public function detailsAction(Order $order) { $request = $this->get('request'); $em = $this->get('doctrine')->getEntityManager(); $router = $this->get('router'); $ppc = $this->get('payment.plugin_controller'); $confirm = new \StdClass(); $form = $this->createFormBuilder($confirm) ->add('save', 'submit', array('label' => 'confirmer')) ->getForm(); if ('POST' === $request->getMethod()) { $form->handleRequest($request); if ($form->isValid()) { $instruction = new PaymentInstruction($order->getAmount(), 978, 'sips'); $ppc->createPaymentInstruction($instruction); $order->setPaymentInstruction($instruction); $em->persist($order); $em->flush($order); return new RedirectResponse($router->generate('payment_gateway', array( 'id' => $order->getId(), ))); } } return array( 'order' => $order, 'form' => $form->createView() ); } }
如前一个动作所示,当用户确认订单时,我们创建一个新的 PaymentInstruction
(有关其工作方式的更多信息,请参阅 JMSPaymentCoreBundle 文档)。然后,用户将被重定向到 payment_gateway
路由。这里是我们将调用 SIPS API 以显示 SIPS 信用卡选择表单的地方。
让我们实现相应的动作
/** * @Route("/gateway/{id}", name="payment_gateway") * @Template() */ public function sipsGatewayAction(Order $order) { $client = $this->get('kptive_payment_sips.client'); $config = array( 'amount' => $order->getAmount() * 100, 'order_id' => $order->getId(), ); $sips = $client->request($config); return array('sips' => $sips); }
在相应的视图中向用户显示表单
{# src/Acme/PaymentBundle/Resources/views/Checkout/sipsGateway.html.twig #}
{{ sips|raw }}
当用户在 SIPS 平台上完成支付工作流程后,他们将被重定向到你之前在包配置部分配置的 normal_return_url
。
让我们实现这个动作
/** * @Route("/complete", name="payment_complete") * @Template() */ public function completeAction(Request $request) { $data = $request->request->get('DATA'); $em = $this->get('doctrine')->getEntityManager(); $client = $this->get('kptive_payment_sips.client'); $response = $client->handleResponseData($data); $order = $em->getRepository('KsPaymentBundle:Order')->find($response['order_id']); $instruction = $order->getPaymentInstruction(); $result = $this->get('kptive_payment_sips.return_handler')->handle($instruction, $response); return array('order' => $order); }
目前,我们没有对订单做任何事情,我们只是处理了银行响应并将支付标记为有效。
JMSPaymentCoreBundle 将触发一个 payment.state_change
事件。所以我们将监听这个事件,并在 PaymentListener
中执行我们想要的任何有用的操作。
<?php namespace Acme\PaymentBundle\EventListener; use Doctrine\ORM\EntityManager; use JMS\Payment\CoreBundle\PluginController\Event\PaymentStateChangeEvent; use JMS\Payment\CoreBundle\Model\PaymentInterface; class PaymentListener { protected $entityManager; public function __construct(EntityManager $entityManager) { $this->entityManager = $entityManager; } public function onPaymentStateChange(PaymentStateChangeEvent $event) { if (PaymentInterface::STATE_DEPOSITED === $event->getNewState()) { $order = $this ->entityManager ->getRepository('AcmePaymentBundle:Order') ->findOneBy(array('paymentInstruction' => $event->getPaymentInstruction())); $order->setPayedAt(new \DateTime()); // Do various things with the Order here // ... $this->entityManager->persist($order); $this->entityManager->flush(); } } }
将其注册为一个服务
<service id="acme_payment.payment_listener" class="Acme\PaymentBundle\EventListener\PaymentListener"> <tag name="kernel.event_listener" event="payment.state_change" method="onPaymentStateChange" /> <argument type="service" id="doctrine.orm.entity_manager"> </service>
就这样!
如果你的客户没有点击银行平台的“返回”按钮,将自动向配置的 automatic_response_url
发出请求。
你可以使用与 normal_return_url
相同的 URL,或者实现自己的。
注意:这些示例没有考虑安全问题。不要忘记检查订单的所有权!
鸣谢
- Hubert Moutot hubert.moutot@gmail.com
非常感谢 Johannes M Schmitt 的出色的 JMSPayementCoreBundle。感谢 https://github.com/Kitano/KitanoPaymentSipsBundle 提供的灵感。
许可
“KptivePaymentSipsBundle”是在MIT许可证下发布的。有关详细信息,请参阅捆绑的LICENSE文件。