PHP
stripe

Stripeのwebhookをトンネリングサービスなしでテストする方法


はじめに

Stripe の webhook を ngrok のようなトンネリングサービスを使わずにテストする方法をまとめておきます。以下のコードは PHP >= 5.5.0 ならそのまま動くと思います。


インストール

$ git clone git@github.com:shimomo/php-stripe-webhook-tester-example.git

$ cd php-stripe-webhook-tester-example
$ composer install


シミュレート

最初に PHP の軽量フレームワーク slim を使って charge.succeeded イベントを受け取るためのエンドポイントを実装しました。内容としては、受け取ったイベントの JSON をそのままオウム返ししています。


index.php

<?php

require __DIR__ . '/vendor/autoload.php';

$app = new Slim\App();
$app->post('/webhooks/charge/succeeded', function ($request, $response, $args) {
return $response->withJson($request->getParsedBody(), 200, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE);
});
$app->run();


そして、ビルトインウェブサーバーを起動します。

$ php -S localhost:8888 -t . index.php

次に Stripe の webhook をシミュレートできるライブラリ php-stripe-webhook-tester を使って charge.succeeded イベントを作成しました。


test.php

<?php

require __DIR__ . '/vendor/autoload.php';

$tester = new TeamTNT\Stripe\WebhookTester();
$tester->setVersion('2018-05-21');
$tester->setEndpoint('http://localhost:8888/webhooks/charge/succeeded');
$response = $tester->triggerEvent('charge.succeeded');

var_dump(json_decode($response->getBody(), true));


最後にイベントを実行して JSON が返ってくれば成功です。

$ php test.php

array(9) {
["created"]=>
int(1326853478)
["livemode"]=>
bool(false)
["id"]=>
string(18) "evt_00000000000000"
["type"]=>
string(16) "charge.succeeded"
["object"]=>
string(5) "event"
["request"]=>
NULL
["pending_webhooks"]=>
int(1)
["api_version"]=>
string(10) "2018-05-21"
["data"]=>
array(1) {
["object"]=>
array(35) {
["id"]=>
string(17) "ch_00000000000000"
["object"]=>
string(6) "charge"
["amount"]=>
int(100)
["amount_refunded"]=>
int(0)
["application"]=>
NULL
["application_fee"]=>
NULL
["balance_transaction"]=>
string(18) "txn_00000000000000"
["captured"]=>
bool(false)
["created"]=>
int(1531523025)
["currency"]=>
string(3) "cad"
["customer"]=>
NULL
["description"]=>
string(43) "My First Test Charge (created for API docs)"
["destination"]=>
NULL
["dispute"]=>
NULL
["failure_code"]=>
NULL
["failure_message"]=>
NULL
["fraud_details"]=>
array(0) {
}
["invoice"]=>
NULL
["livemode"]=>
bool(false)
["metadata"]=>
array(0) {
}
["on_behalf_of"]=>
NULL
["order"]=>
NULL
["outcome"]=>
NULL
["paid"]=>
bool(true)
["receipt_email"]=>
NULL
["receipt_number"]=>
NULL
["refunded"]=>
bool(false)
["refunds"]=>
array(5) {
["object"]=>
string(4) "list"
["data"]=>
array(0) {
}
["has_more"]=>
bool(false)
["total_count"]=>
int(0)
["url"]=>
string(47) "/v1/charges/ch_1CnaIfLOXa6akpHRr2y632GC/refunds"
}
["review"]=>
NULL
["shipping"]=>
NULL
["source"]=>
array(23) {
["id"]=>
string(19) "card_00000000000000"
["object"]=>
string(4) "card"
["address_city"]=>
NULL
["address_country"]=>
NULL
["address_line1"]=>
NULL
["address_line1_check"]=>
NULL
["address_line2"]=>
NULL
["address_state"]=>
NULL
["address_zip"]=>
NULL
["address_zip_check"]=>
NULL
["brand"]=>
string(4) "Visa"
["country"]=>
string(2) "US"
["customer"]=>
string(18) "cus_00000000000000"
["cvc_check"]=>
string(4) "pass"
["dynamic_last4"]=>
NULL
["exp_month"]=>
int(7)
["exp_year"]=>
int(2019)
["fingerprint"]=>
string(16) "EB8zTN6S64nsJn2C"
["funding"]=>
string(6) "credit"
["last4"]=>
string(4) "4242"
["metadata"]=>
array(0) {
}
["name"]=>
NULL
["tokenization_method"]=>
NULL
}
["source_transfer"]=>
NULL
["statement_descriptor"]=>
NULL
["status"]=>
string(9) "succeeded"
["transfer_group"]=>
NULL
}
}
}


おわりに

トンネリングサービスを使って実際のイベントを処理したほうがテストとしては確実だと思いますけどね。