如何处理多个环境:使用 paypal webhooks 进行开发、暂存和生产?

How to handle multiple environments: dev, staging and production with paypal webhooks?

我想要三个环境,我可以在其中测试和使用 paypal webhook。我目前的方法是为 paypal 开发人员门户中的每个环境创建新的 webhook,并在请求到达时检查它是否适用于该环境。 paypal如何处理多个webhook url,如果环境不正确应该返回什么状态码?

在我们的一个项目中,我们根据环境使用不同的配置变量。

对于开发者

$config['paypal.settings'] = array(
        'mode'=> "sandbox", //'live' or 'sandbox'(default)
        'clientID'=>"CLIENT_ID_FOR_DEV" ,
        'secret'=> "SUPERSECRETCLIENT_SECRET_FOR_DEV" ,
        'currency'=>'EUR',
        'logEnabled' => false,
        'logDir'=>__DIR__ . '/../logs'
);

对于产品:

$config['paypal.settings'] = array(
        'mode'=> "live", 
        'clientID'=>"CLIENT_ID_FOR_PROD" ,
        'secret'=> "SUPERSECRETCLIENT_SECRET_FOR_PROD" ,
        'currency'=>'EUR',
        'logEnabled' => false,
        'logDir'=>__DIR__ . '/../logs'
);

我们的开发和生产环境显然位于 2 个不同的域上,这些域在 paypal 界面上为每个 CLIENT_ID 配置。

在 Paypal 调用的 webhook 控制器中,我们有:

class WebhookController{
  function paypalPingBackAction($request){
      $paypalSettings = //get paypal settings
      $isLive = ($paypalSettings["sandbox"] ?? "sandbox") == "live";

      $currentDomain = $request->getDomain();

     // now we have enough information (domain and sandbox)
     // to do things accordingly

  }
}

Paypal 并不真正关心您发回的代码。但是如果你发送一个500,他会稍后重试。所以也许,如果一切顺利,只是 return 一个空的 201 accepted !

像下面这样创建一个 Class 以保留在您的应用程序的开头。让它初始化一次。

class App {
    private static $env_status = null;
    private static $paypal_settings = [];

    const ENV_PRODUCTION = "production";
    const ENV_STAGING = "staging";
    const ENV_DEV = "development";

    public static function init() {
        // Set environment status.  
        // You can also parse domain name and depending on your domain, you can set the environment status.
        self::$env_status = getenv("ENV_STATUS");   // getenv() Gets from Environment variable. You'll need set clear_env = no in php config for this to work.

        switch(self::$env_status) {
            case App::ENV_PRODUCTION:
                self::$paypal_settings = [
                    "mode" => "live"
                    "clientID" => "PRODUCTION_CLIENT_ID" ,
                    "secret" => "PRODUCTION_SECRET" ,
                    "currency" => "USD",
                    "webhook" => "https://example.com/live_webhook_endpoint"
                ];

                break;

            case App::ENV_STAGING:
                self::$paypal_settings = [
                    "mode"=> "sandbox"
                    "clientID"=> "STAGING_CLIENT_ID" ,
                    "secret"=> "STAGING_SECRET" ,
                    "currency"=> "USD",
                    "webhook" => "https://example.com/staging_webhook_endpoint"
                ];

                break;

            default:
                // ENV_DEV settings
                self::$paypal_settings = [
                    "mode"=> "sandbox"
                    "clientID"=> "DEVELOPMENT_CLIENT_ID" ,
                    "secret"=> "DEVELOPMENT_SECRET" ,
                    "currency"=> "USD",
                    "webhook" => "https://example.com/development_webhook_endpoint"
                ];
                break;
        }
    }

    public static function env_status() {
        return self::$env_status;
    }

    public static function paypal_settings() {
        return self::$paypal_settings;
    }

    // You can also create seprate function if you just want webhook URL. 
    // You can define in different variable also if that's the case.
    public static function paypal_webhook_url() {
        return self::$paypal_settings['webhook'];
    }

} App::init();

然后,无论何时您想要获取贝宝设置,您都可以在应用程序的任何位置调用它。

$paypay_settings = App::paypal_settings();

或者如果您只需要 paypal webhook URL

$paypal_webhook_url = App::paypal_webhook_url();

这样您就不必在代码的其他部分保留任何条件。所有的条件都放在一个地方,以后更新起来更容易。

paypal 如何处理多个 webhook url。

您需要点击 PayPal 沙盒 URL 才能点击 staging/development 环境。

如果环境不正确应该返回什么状态码?

HTTP 400。因为这将是一个无效请求。

Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400

The HyperText Transfer Protocol (HTTP) 400 Bad Request response status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).