7

私は、Sylius (sylius/sylius-standard, v0.16) を使用して従来のオフライン決済ゲートウェイを実装する方法について頭を悩ませてきました。

これまでのところ、バンドルの build() メソッドでこれを取得しました。

public function build(ContainerBuilder $container)
{
    /** @var PayumExtension $payum */
    $payum = $container->getExtension('payum');
    $payum->addGatewayFactory(new PayWayOffsiteGatewayFactory());
}

ここに私の config.yml があります:

sylius_payment:
    gateways:
        payway_offsite: PayWay

payum:
    gateways:
        payway_offsite:
            payway_offsite:
                secret_key: %tcompayway.secret_key%
                shop_id:    %tcompayway.shop_id%
                username:   %tcompayway.username%
                password:   %tcompayway.password%
                sandbox:    %tcompayway.sandbox%

%compayway.*% フィールドは、この部分をスキップして、もちろん問題なく構成されています。次に、PayWayOffsiteGatewayFactory クラスでこれを取得しました。

class PayWayOffsiteGatewayFactory extends AbstractGatewayFactory
{
    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'payway_offsite';
    }

    /**
     * {@inheritdoc}
     */
    public function addConfiguration(ArrayNodeDefinition $builder)
    {
        parent::addConfiguration($builder);

        $builder->children()
            ->scalarNode('secret_key')->isRequired()->cannotBeEmpty()->end()
            ->scalarNode('shop_id')->isRequired()->cannotBeEmpty()->end()
            ->scalarNode('username')->isRequired()->cannotBeEmpty()->end()
            ->scalarNode('password')->isRequired()->cannotBeEmpty()->end()
            ->booleanNode('sandbox')->defaultTrue()->end()
            ->end();
    }

    /**
     * {@inheritDoc}
     */
    protected function getPayumGatewayFactoryClass()
    {
        return 'WebBurza\PaymentBundle\Payum\PayWay\PayWayGatewayFactory';
    }

    /**
     * {@inheritDoc}
     */
    protected function getComposerPackage()
    {
        return 'webburza/tcompayway';
    }
}

PayWayGatewayFactory クラス:

class PayWayGatewayFactory extends GatewayFactory
{
    /**
     * {@inheritDoc}
     * @throws \Payum\Core\Exception\InvalidArgumentException
     */
    protected function populateConfig(ArrayObject $config)
    {
        $config->defaults(array(
            'payum.factory_name'            => 'payway_offsite',
            'payum.factory_title'           => 'PayWay Offsite',
            'payum.action.capture'          => new CaptureOffsiteAction(),
            'payum.action.capture_null'     => new CaptureOffsiteNullAction(),
            'payum.action.status'           => new StatusAction(),
            'payum.action.convert_payment'  => new ConvertPaymentAction(),
        ));

        if (false == $config['payum.api']) {
            $config['payum.default_options'] = array(
                'secret_key'    => '',
                'shop_id'       => '',
                'username'      => '',
                'password'      => '',
                'sandbox'       => true
            );
            $config->defaults($config['payum.default_options']);
            $config['payum.required_options'] = [
                'secret_key',
                'shop_id',
                'username',
                'password',
                'sandbox'
            ];

            $config['payum.api'] = function (ArrayObject $config) {

                $config->validateNotEmpty($config['payum.required_options']);

                $api = new Api([
                    'secret_key'=> $config['secret_key'],
                    'shop_id'   => $config['shop_id'],
                    'username'  => $config['username'],
                    'password'  => $config['password'],
                    'sandbox'   => $config['sandbox'],
                ], $config['payum.http_client']);

                return $api;

            };
        }
    }
}

これまでのところ、私はこれが多かれ少なかれ大丈夫だという印象を受けています (間違っていたら訂正してください)。CaptureOffsiteAction の execute メソッドにたどり着きました。

public function execute($captureRequest)
    {
        RequestNotSupportedException::assertSupports($this, $captureRequest);
        $model = ArrayObject::ensureArrayObject($captureRequest->getModel());

        $httpRequest = new GetHttpRequest();
        $this->gateway->execute($httpRequest);

        if ($httpRequest->method === 'POST') {
            $status = new GetHumanStatus($model);

            if (isset($httpRequest->request['pgw_transaction_id']) && $httpRequest->request['pgw_transaction_id'] > 0) {
                // mark this order id as paid, convert cart to order, etc.

            } else {
                // mark as failed/cancelled, redirect back to cart
            }
            return;

        }

        $model['successUrl'] = $captureRequest->getToken()->getTargetUrl();
        $model['failureUrl'] = $captureRequest->getToken()->getTargetUrl();
        $offsiteUrl = $this->api->getOffsiteUrl();

        $data    = $this->api->prepareOffsitePayment($model->toUnsafeArray());
        $headers = ['application/x-www-form-urlencoded'];

        throw new HttpPostRedirect(
            $offsiteUrl,
            $data,
            200,
            $headers
        );

    }

まず、これが正しいかどうかを確認してみましょう - キャプチャ プロセス (メソッドの実行) を開始すると、期待どおりに機能し、メソッドの下部に到達し、成功 URL と失敗 URL を作成し、オフサイトの支払い、ハッシュなどを準備します。それは最終的に、正しい注文 ID、価格などで HttpPostRedirect を介して支払いゲートウェイに到達します。この部分は問題ありません。

支払い後、成功 URL に戻ると、CaptureOffsiteAction::execute に戻り、pgw_transaction_id を確認します。これが設定されている場合は、支払いから戻ったことを意味し、注文の支払いが成功したか、支払いがキャンセル/失敗したかを検出する必要があります。

質問は次のとおりです。

  • 支払いが成功した場合 - 注文を「閉じる」にはどうすればよいですか (カートを注文に変換する、支払いをキャプチャ済みとしてマークするなど)。

  • 他の支払いゲートウェイには他にもたくさんの方法があることがわかります-ポストリダイレクトによるオフサイト支払いのみに興味があるとしましょう-StatusActionは何をしますか? そして、それはいつ呼ばれますか?

これまでのところ、Payum (および PayumBundle) は非常に紛らわしいことがわかりました。OmniPay (Sylius に関連しない他のプロジェクト) を使用して 1 日以内に 2 つのオフサイト ゲートウェイを実装することができましたが、この Payum の問題を解決できないようです。:(

事前に感謝します。

4

1 に答える 1