{"id":13609612,"url":"https://github.com/mewebstudio/laravel-pos","last_synced_at":"2025-05-16T15:03:33.463Z","repository":{"id":37677639,"uuid":"143802483","full_name":"mewebstudio/laravel-pos","owner":"mewebstudio","description":"Türk bankaları için sanal pos paketi (Laravel 5/6/7/8)","archived":false,"fork":false,"pushed_at":"2025-02-26T14:27:44.000Z","size":65,"stargazers_count":96,"open_issues_count":1,"forks_count":38,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-04-03T11:09:34.506Z","etag":null,"topics":["3d","3dpay","3dsecure","est","garanti","laravel","laravel-est","laravel-pos","laravel-sanal-pos","laravelpos","php","pos","posnet","sanalpos"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mewebstudio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-07T01:28:42.000Z","updated_at":"2025-03-27T20:51:32.000Z","dependencies_parsed_at":"2024-08-01T19:43:26.734Z","dependency_job_id":"547f00f4-2cdb-488e-9d32-636ec4f25a97","html_url":"https://github.com/mewebstudio/laravel-pos","commit_stats":{"total_commits":31,"total_committers":5,"mean_commits":6.2,"dds":0.3870967741935484,"last_synced_commit":"51f6df8bab62c84d97f5622d59a7051a88df09dc"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mewebstudio%2Flaravel-pos","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mewebstudio%2Flaravel-pos/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mewebstudio%2Flaravel-pos/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mewebstudio%2Flaravel-pos/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mewebstudio","download_url":"https://codeload.github.com/mewebstudio/laravel-pos/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248564657,"owners_count":21125408,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d","3dpay","3dsecure","est","garanti","laravel","laravel-est","laravel-pos","laravel-sanal-pos","laravelpos","php","pos","posnet","sanalpos"],"created_at":"2024-08-01T19:01:36.496Z","updated_at":"2025-04-12T11:48:10.106Z","avatar_url":"https://github.com/mewebstudio.png","language":"PHP","funding_links":[],"categories":["PHP"],"sub_categories":[],"readme":"# Türk bankaları için sanal pos paketi (Laravel)\n\n## Temel Paket\n[mews/pos](https://github.com/mewebstudio/pos)\n\n## Ana başlıklar\n\n- [Minimum Gereksinimler](#minimum-gereksinimler)\n- [Kurulum](#kurulum)\n- [Kullanım (3D Secure Ödeme)](#3d-secure-odeme-ornek-kullanim)\n- [Troubelshoots](#troubleshoots)\n- [Konfigurasyon Yapısı ve Örnekler](./docs/EXAMPLE_CONFIGURATIONS.md)\n- [API ve 3D Form verisini degiştirme](./docs/EXAMPLE-API-ISTEK-VE-3D-FORM-VERSINI-DEGISTIRME.md)\n\n### Minimum Gereksinimler\n- PHP \u003e= 7.4\n- mews/pos ^1.6\n- laravel 8, 9, 10, 11\n\n### Kurulum\n1. \n    ```sh\n    $ composer require mews/laravel-pos\n    $ php artisan vendor:publish --tag=laravel-pos\n    ```\n\n2. `/config/laravel-pos.php` ayarınızı elinizde gateway bilgileri göre güncelleyiniz.\n   Örnek konfigurasyon:\n    ```php\n    \u003c?php\n    # /config/laravel-pos.php\n    return [\n        'banks' =\u003e [\n            # array keyleri unique olmalıdır, bu keylerle Controller'larda su sekilde erisilebilir:\n            # $this-\u003econtainer-\u003eget('laravel-pos:gateway:kuveytpos');\n            'kuveytpos' =\u003e [ # ilk sıradaki banka injection için default olur.\n                'gateway_class'     =\u003e \\Mews\\Pos\\Gateways\\KuveytPos::class,\n                'test_mode'         =\u003e true,\n                'lang'              =\u003e \\Mews\\Pos\\PosInterface::LANG_TR,\n                'credentials'       =\u003e [\n                    'payment_model' =\u003e \\Mews\\Pos\\PosInterface::MODEL_3D_SECURE,\n                    'merchant_id'   =\u003e 'xxx',\n                    'terminal_id'   =\u003e 'yyyyyyy',\n                    'user_name'     =\u003e 'zzzzzzz',\n                    'enc_key'       =\u003e 'www123',\n                ],\n                'gateway_endpoints' =\u003e [\n                    'payment_api'     =\u003e 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home',\n                    'gateway_3d'      =\u003e 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelPayGate',\n                    'query_api'       =\u003e 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc?wsdl',\n                ],\n            ],\n            'estpos_payten' =\u003e [\n                'gateway_class'     =\u003e \\Mews\\Pos\\Gateways\\EstV3Pos::class,\n                'test_mode'         =\u003e true,\n                'lang'              =\u003e \\Mews\\Pos\\PosInterface::LANG_TR,\n                'credentials'       =\u003e [\n                    'payment_model' =\u003e \\Mews\\Pos\\PosInterface::MODEL_3D_SECURE,\n                    'merchant_id'   =\u003e '7001132146464',\n                    'user_name'     =\u003e 'ISBXXXXX',\n                    'user_password' =\u003e 'ISBYYYYY',\n                    'enc_key'       =\u003e 'TRPZZZZZ',\n                ],\n                'gateway_endpoints' =\u003e [\n                    'payment_api'     =\u003e 'https://entegrasyon.asseco-see.com.tr/fim/api',\n                    'gateway_3d'      =\u003e 'https://entegrasyon.asseco-see.com.tr/fim/est3Dgate',\n                    'gateway_3d_host' =\u003e 'https://sanalpos.sanalakpos.com.tr/fim/est3Dgate',\n                ],\n            ],\n        ],\n    ];\n    ```\n\n3. PHP Session kullanıyorsanız 3D ödemeler için session'i alttaki şekilde ayarlamanız gerekir.\n    \n    **Laravel 11** için environment değişkenleri şu şekilde olacak:\n    ```\n    SESSION_SECURE_COOKIE=true\n    SESSION_SAME_SITE=Lax # ya da SESSION_SAME_SITE=None deneyiniz.\n    ```\n    **Laravel 10, 9, 8** için ise \n   1. Environment'da `SESSION_SECURE_COOKIE=true` yapılacak \n   2. Ve `/config/session.php`'de `same_site` değeri güncellenecek:\n       ```php\n       # /config/session.php:\n       return [\n           // ...\n           'same_site' =\u003e 'lax', # ya da 'none' deneyiniz.\n       ]\n       ```\n   _Değişikliklerden sonra var olan session'i silip yeni session oluşturunuz._\n\n4. 3D ödemelerde bankadan websiteye geri redirect edilecek URL'larda (success/fail URL'lar) CSRF kapatılması gerekir.\n\n   **Laravel 11** `withMiddleware()` method'la ayarı yapabilirsiniz.\n\n    ```php\n        \u003c?php\n        # /bootstrap/app.php\n        \n        use Illuminate\\Foundation\\Application;\n        use Illuminate\\Foundation\\Configuration\\Exceptions;\n        use Illuminate\\Foundation\\Configuration\\Middleware;\n        \n        return Application::configure(basePath: dirname(__DIR__))\n            // ...\n            -\u003ewithMiddleware(function (Middleware $middleware) {\n                $middleware-\u003evalidateCsrfTokens(except: [\n                    '/payment/3d/response'\n                ]);\n            });\n    ```\n\n    **Laravel 10, 9, 8** ise `/app/Http/Middleware/VerifyCsrfToken.php`'de ayarlayabilirsiniz.\n\n    ```php\n    \u003c?php\n    # /app/Http/Middleware/VerifyCsrfToken.php\n    namespace App\\Http\\Middleware;\n    \n    use Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken as Middleware;\n    \n    class VerifyCsrfToken extends Middleware\n    {\n        protected $except = [\n            // success ve fail URL'lar buraya eklenecek:\n            '/payment/3d/response',\n        ];\n    }\n    ```\n\n5. **KuveytPos** için API isteklere ekstra alanlar eklemeniz gerekiyor, bunun için Event Listener'ları kullanabilirsiniz. Örnek:\n   \n    ```php\n    \u003c?php\n    # /app/Listeners/KuveytPosV2RequestDataPreparedEventListener.php:\n    namespace App\\Listeners;\n    \n    use Mews\\Pos\\Event\\RequestDataPreparedEvent;\n    \n    /**\n     * KuveytPos TDV2.0.0 odemenin calismasi icin zorunlu eklenmesi gereken alan var.\n     */\n     class KuveytPosV2RequestDataPreparedEventListener\n    {\n        public function __invoke(RequestDataPreparedEvent $event): void\n        {\n            if ($event-\u003egetGatewayClass() !== \\Mews\\Pos\\Gateways\\KuveytPos::class) {\n                return;\n            }\n            /**\n             * ekstra eklenmesi gereken verileri isteseniz $order icine ekleyip sonra o verilere\n             * $event-\u003egetOrder() ile erisebilirsiniz.\n             */\n            $additionalRequestDataForKuveyt = [\n                'DeviceData'     =\u003e [\n                    'DeviceChannel' =\u003e '02',\n                ],\n                'CardHolderData' =\u003e [\n                    'BillAddrCity'     =\u003e 'İstanbul',\n                    'BillAddrCountry'  =\u003e '792',\n                    'BillAddrLine1'    =\u003e 'XXX Mahallesi XXX Caddesi No 55 Daire 1',\n                    'BillAddrPostCode' =\u003e '34000',\n                    'BillAddrState'    =\u003e '40',\n                    'Email'            =\u003e 'xxxxx@gmail.com',\n                    'MobilePhone'      =\u003e [\n                        'Cc'         =\u003e '90',\n                        'Subscriber' =\u003e '5554567899',\n                    ],\n                ],\n            ];\n            $requestData                    = $event-\u003egetRequestData();\n            $requestData                    = \\array_merge_recursive($requestData, $additionalRequestDataForKuveyt);\n            $event-\u003esetRequestData($requestData);\n        }\n    }\n    ```\n\n    Sonra bu yeni Listener'i `AppServiceProvider`'da register etmeniz gerekiyor.\n    \n    ```php\n    # /app/Providers/AppServiceProvider.php\n    namespace App\\Providers;\n    \n    class AppServiceProvider extends ServiceProvider\n    {\n        public function boot(): void\n        {\n            // ...\n            \\Illuminate\\Support\\Facades\\Event::listen(\n                \\Mews\\Pos\\Event\\RequestDataPreparedEvent::class,\n                \\App\\Listeners\\KuveytPosV2RequestDataPreparedEventListener::class\n            );\n        }\n    }\n    ```\n\n\n\n### 3D Secure Odeme Ornek Kullanim\n\n```php\n\u003c?php\n\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Http\\Request;\nuse Mews\\Pos\\Entity\\Card\\CreditCardInterface;\nuse Mews\\Pos\\Exceptions\\CardTypeNotSupportedException;\nuse Mews\\Pos\\Exceptions\\CardTypeRequiredException;\nuse Mews\\Pos\\Exceptions\\HashMismatchException;\nuse Mews\\Pos\\Factory\\CreditCardFactory;\nuse Mews\\Pos\\Gateways\\PayFlexV4Pos;\nuse Mews\\Pos\\PosInterface;\n\nclass ThreeDSecurePaymentController extends Controller\n{\n    private string $paymentModel = PosInterface::MODEL_3D_SECURE;\n\n    // Tek banka örnegi:\n    // Tek banka anlamı /config/laravel-pos.php'de sadece bir banka tanımlanmış olmasıdır.\n    public function __construct(\n        private PosInterface $pos,\n    ) {\n    }\n    \n    // START: birden fazla banka ile örnek:\n//    public function __construct(\n//        private Container $container,\n//    ) {}\n//    \n//    private function getPosService(string $bank): PosInterface\n//    {\n//        return $this-\u003econtainer-\u003eget('laravel-pos:gateway:'.$bank);\n//    }\n    // END: birden fazla banka ile örnek\n\n    /**\n     * route: /payment/3d/form\n     * Kullanicidan kredi kart bilgileri alip buraya POST ediyoruz\n     */\n    public function form(Request $request)\n    {\n        $session = $request-\u003egetSession();\n    \n        // START: birden fazla banka ile örnek\n//        $secilenBanka = $request-\u003eget('installment') \u003e 1 ? 'kuveytpos' : 'estpos_payten';\n//        $this-\u003epos = $this-\u003eposService($secilenBanka);\n//        $session-\u003eset('secilen_banka', $secilenBanka);\n        // END: birden fazla banka ile örnek \n\n        $transaction = $request-\u003eget('tx', PosInterface::TX_TYPE_PAY_AUTH);\n\n        $callbackUrl = url(\"/payment/3d/response\");\n        $order       = $this-\u003ecreateNewOrder(\n            $this-\u003epaymentModel,\n            $callbackUrl,\n            $request-\u003egetClientIp(),\n            $request-\u003eget('currency', PosInterface::CURRENCY_TRY),\n            $request-\u003eget('installment'),\n        );\n        $session-\u003eset('order', $order);\n\n        $card = $this-\u003ecreateCard($this-\u003epos, $request-\u003erequest-\u003eall());\n        \n        /**\n         * PayFlex'te provizyonu (odemeyi) tamamlamak icin tekrar kredi kart bilgileri isteniyor,\n         * bu yuzden kart bilgileri kaydediyoruz\n         */\n        if ($this-\u003epos::class === PayFlexV4Pos::class) {\n            // Laravel 8'de set() yerine put() metodu kullanmanız gerekiyor.\n            $session-\u003eset('card', $request-\u003erequest-\u003eall());\n        }\n        $session-\u003eset('tx', $transaction);\n\n        try {\n            $formData = $this-\u003epos-\u003eget3DFormData(\n            $order,\n            $this-\u003epaymentModel,\n            $transaction,\n            $card,\n            /**\n            * MODEL_3D_SECURE veya MODEL_3D_PAY ödemelerde kredi kart verileri olmadan\n            * form verisini oluşturmak için true yapabilirsiniz.\n            * Yine de bazı gatewaylerde kartsız form verisi oluşturulamıyor.\n            */\n            false\n            );\n        } catch (\\Throwable $e) {\n            dd($e);\n        }\n\n        return view('redirect-form', [\n            'formData' =\u003e $formData,\n        ]);\n    }\n\n    /**\n     * route: /payment/3d/response\n     * Kullanici bankadan geri buraya redirect edilir.\n     * Bu route icin CSRF disable edilmesi gerekiyor.\n     */\n    public function response(Request $request)\n    {\n        $session = $request-\u003egetSession();\n\n        // START: birden fazla banka ile örnek\n        // $this-\u003epos = $this-\u003eposService($session-\u003eget('secilen_banka'));\n        // END: birden fazla banka ile örnek \n        \n        $transaction = $session-\u003eget('tx', PosInterface::TX_TYPE_PAY_AUTH);\n\n        // bankadan POST veya GET ile veri gelmesi gerekiyor\n        if (($request-\u003egetMethod() !== 'POST')\n            // PayFlex-CP GET request ile cevapliyor\n            \u0026\u0026 ($request-\u003egetMethod() === 'GET' \u0026\u0026 ($this-\u003epos::class !== \\Mews\\Pos\\Gateways\\PayFlexCPV4Pos::class || [] === $request-\u003equery-\u003eall()))\n        ) {\n            return redirect('/');\n        }\n\n        $card = null;\n        if ($this-\u003epos::class === \\Mews\\Pos\\Gateways\\PayFlexV4Pos::class) {\n            // bu gateway için ödemeyi tamamlarken tekrar kart bilgisi lazım.\n            $savedCard = $session-\u003eget('card');\n            $card      = $this-\u003ecreateCard($this-\u003epos, $savedCard);\n        }\n\n        $order = $session-\u003eget('order');\n        if (!$order) {\n            throw new \\Exception('Sipariş bulunamadı, session sıfırlanmış olabilir.');\n        }\n\n        try {\n            $this-\u003epos-\u003epayment($this-\u003epaymentModel, $order, $transaction, $card);\n        } catch (HashMismatchException $e) {\n            dd($request-\u003erequest-\u003eall(), $request-\u003equery-\u003eall(), $e);\n        } catch (\\Exception|\\Error $e) {\n            dd($request-\u003erequest-\u003eall(), $request-\u003equery-\u003eall(), $e);\n        }\n\n        $response = $this-\u003epos-\u003egetResponse();\n\n        // iptal, iade, siparis durum sorgulama islemleri yapabilmek icin $response'u kaydediyoruz\n        $session-\u003eset('last_response', $response);\n\n        if ($this-\u003epos-\u003eisSuccess()) {\n            echo 'success';\n        }\n\n        dd($response);\n    }\n\n    private function createNewOrder(\n        string $paymentModel,\n        string $callbackUrl,\n        string $ip,\n        string $currency,\n        ?int   $installment = 0,\n        string $lang = PosInterface::LANG_TR\n    ): array\n    {\n        $orderId = date('Ymd').strtoupper(substr(uniqid(sha1(time())), 0, 4));\n\n        $order = [\n            'id'          =\u003e $orderId,\n            'amount'      =\u003e 10.01,\n            'currency'    =\u003e $currency,\n            'installment' =\u003e $installment,\n            'ip'          =\u003e filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? $ip : '127.0.0.1',\n        ];\n\n        if (in_array($paymentModel, [\n            PosInterface::MODEL_3D_SECURE,\n            PosInterface::MODEL_3D_PAY,\n            PosInterface::MODEL_3D_HOST,\n            PosInterface::MODEL_3D_PAY_HOSTING,\n        ], true)) {\n            $order['success_url'] = $callbackUrl;\n            $order['fail_url']    = $callbackUrl;\n        }\n\n        if ($lang) {\n            //lang degeri verilmezse account (EstPosAccount) dili kullanilacak\n            $order['lang'] = $lang;\n        }\n\n        return $order;\n    }\n\n    private function createCard(PosInterface $pos, array $card): CreditCardInterface\n    {\n        try {\n            return CreditCardFactory::createForGateway(\n                $pos,\n                $card['number'],\n                $card['year'],\n                $card['month'],\n                $card['cvv'],\n                $card['name'],\n                $card['type'] ?? null\n            );\n        } catch (CardTypeRequiredException|CardTypeNotSupportedException $e) {\n            dd($e);\n        } catch (\\LogicException $e) {\n            dd($e);\n        }\n    }\n}\n```\n\n```php\n# /routes/web.php\nRoute::match(['POST'], '/payment/3d/form', [\\App\\Http\\Controllers\\ThreeDSecurePaymentController::class, 'form']);\nRoute::match(['GET','POST'], '/payment/3d/response', [\\App\\Http\\Controllers\\ThreeDSecurePaymentController::class, 'response']);\n```\n\n```html\n\u003c!--/resources/views/redirect-form.blade.php--\u003e\n@if(is_string($formData))\n    {!! $formData !!}\n@else\n   \u003cform method=\"{{ $formData['method'] }}\" action=\"{{ $formData['gateway'] }}\"  class=\"redirect-form\" role=\"form\"\u003e\n      @foreach($formData['inputs'] as $key =\u003e $value)\n      \u003cinput type=\"hidden\" name=\"{{ $key }}\" value=\"{{ $value }}\"\u003e\n      @endforeach\n      \u003cdiv class=\"text-center\"\u003eRedirecting...\u003c/div\u003e\n      \u003chr\u003e\n      \u003cdiv class=\"form-group text-center\"\u003e\n         \u003cbutton type=\"submit\" class=\"btn btn-lg btn-block btn-success\"\u003eSubmit\u003c/button\u003e\n      \u003c/div\u003e\n   \n   \u003c/form\u003e\n   \u003cscript\u003e\n      // Formu JS ile otomatik submit ederek kullaniciyi banka gatewayine yonlendiriyoruz.\n      let redirectForm = document.querySelector('form.redirect-form');\n      if (redirectForm) {\n         redirectForm.submit();\n      }\n   \u003c/script\u003e\n@endif\n```\n\n### Troubleshoots\n\n- Error: \"_cURL error 60: SSL certificate problem: unable to get local issuer certificate (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://..._\"\n  Genellikle lokal ortamda bu sorunla karşılaşabilirsiniz. Lokal ortamınızda CA certificate bulunmadığında oluşur.\n  Bu durumda sunucuda çalıştırmayı deneyiniz.\n\n\nLicense\n----\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmewebstudio%2Flaravel-pos","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmewebstudio%2Flaravel-pos","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmewebstudio%2Flaravel-pos/lists"}