Rails:Paypal 端点 /v2/checkout/orders 返回 http 401

Posted

技术标签:

【中文标题】Rails:Paypal 端点 /v2/checkout/orders 返回 http 401【英文标题】:Rails: Paypal endpoint /v2/checkout/orders returns http 401 【发布时间】:2021-08-03 06:38:57 【问题描述】:

此 paypal 结帐代码在 localhost 沙箱上完美运行,但在 Heroku 上失败并显示 401。当用户单击 Paypal 按钮时,会显示一个弹出式登录窗口并点击后端控制器 /orders/create_order .

前端 JS

<script src="https://www.paypal.com/sdk/js?client-id=<%=@client_id%>"></script>
<script>
paypal.Buttons(
  env: '<%= @env %>', // Valid values are sandbox and live.
  createOrder: async () => 
      const config = 
          method: 'POST',
          headers: 
              'Accept': 'application/json',
              'Content-Type': 'application/json'
          ,
          body: JSON.stringify(key: '<%= @order.key %>')
      
      const response = await fetch('/orders/create_order', config);
      const responseData = await response.json();
      return responseData.token;
  ,
  onApprove: async (data) => 
    const response = await fetch('/orders/capture_order', 
      method: 'POST',
      headers: 
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      ,
      body: JSON.stringify(token: data.orderID)
    );
    const responseData = await response.json();
    if (responseData.status === 'COMPLETED') 
      alert('Payment success!');
      location.reload();
    
  
).render('#paypal-button-container');
</script>

后端 Rails 控制器

  before_action :paypal_init

  def paypal_init
    @env = ENV["PAYPAL_ENV"]
    @client_id = ENV["PAYPAL_CLIENT_ID"]
    client_secret = ENV["PAYPAL_CLIENT_SECRET"]
    environment = PayPal::SandboxEnvironment.new @client_id, client_secret
    @client = PayPal::PayPalHttpClient.new environment
  end

  def create_order
    ky = params[:key]
    order = Order.where(key:ky).first

    request = PayPalCheckoutSdk::Orders::OrdersCreateRequest::new
    encoded   = Base64.strict_encode64("#ENV["PAYPAL_CLIENT_ID"]:#ENV["PAYPAL_CLIENT_SECRET"]")
    request.headers["Authorization"] = "Basic #encoded"
    request.request_body(
      :intent => 'CAPTURE',
      :purchase_units => [
        
          :amount => 
            :currency_code => 'USD',
            :value => order.price.to_s
          
        
      ]
    )

    begin
      response = @client.execute(request)
      result = response.result
      order.token = result.id
      if order.save!
        return render :json => :token => order.token, :status => :ok
      end
    rescue PayPalHttp::HttpError => ioe
      puts ioe.status_code
      puts ioe.headers["debug_id"]
    end
  end

在请求对象上执行puts 会得到这个

"headers":"Content-Type":"application/json","Authorization":"Basic somevalue","body":"intent":"CAPTURE","purchase_units":[ "amount":"currency_code":"USD","value":"10"],"verb":"POST","path":"/v2/checkout/orders?"

我的尝试

    我已经检查了 PAYPAL_CLIENT_ID 和 PAYPAL_CLIENT_SECRET 环境变量,它们使用了正确的生产值

    我尝试在 Heroku 上将 PAYPAL_ENV 更改为 liveproduction

    无数次重启 Heroku 应用

    出于绝望尝试添加此行

request.headers["Authorization"] = "基本#encoded"

    把我所有的指甲都嚼了

它不会停止返回 401,但可以在带有 Sandbox 的 localhost 上完美运行。

【问题讨论】:

【参考方案1】:

环境 = PayPal::SandboxEnvironment.new @client_id, client_secret

如果您尝试使用生产客户端/秘密进行实时处理,这将是一个问题。

使 API 行为取决于您配置的 PAYPAL_ENV,而不是忽略它。

【讨论】:

【参考方案2】:

通过检查 'sandbox' 或 'live' 的 env 变量更新我的代码,然后在我们不在沙箱中时初始化 LiveEnvironment

  def paypal_init
    @env = ENV["PAYPAL_ENV"]
    @client_id = ENV["PAYPAL_CLIENT_ID"]
    client_secret = ENV["PAYPAL_CLIENT_SECRET"]
    if @env == 'sandbox'
      environment = PayPal::SandboxEnvironment.new @client_id, client_secret
    else
      environment = PayPal::LiveEnvironment.new @client_id, client_secret
    end
    @client = PayPal::PayPalHttpClient.new environment
  end

并删除了create_order 方法中的 Authorization 标头内容

encoded = Base64.strict_encode64("#ENV["PAYPAL_CLIENT_ID"]:#ENV["PAYPAL_CLIENT_SECRET"]")
request.headers["Authorization"] = "Basic #encoded"

现在可以了

【讨论】:

以上是关于Rails:Paypal 端点 /v2/checkout/orders 返回 http 401的主要内容,如果未能解决你的问题,请参考以下文章

更改 PayPal REST 端点

PayPal SDK:PayPal 错误:找不到 live.dyson 的端点

具有 Paypal 权限和 Paypal Express Checkout 的 Rails

使用 Rails 3 的 PayPal 自适应支付

Java / PayPal 集成指向错误的端点

(Rails) 使用 Braintree v.zero SDK 进行 PayPal 支付