PHP PayPal のアクセストークンを生成するには?

ショコラ
ショコラ

PHP PayPal のアクセストークンを生成するには?

PayPal のアクセストークンを取得するサンプルプログラムです。
cURL ではなく file_get_contents を使用しています。

というか、アクセストークンだけではないですね。こちらのページに PayPal まとめていきます。

元ネタは↓こちらなのです。
https://developer.paypal.com/docs/checkout/standard/integrate/

もっさん先輩
もっさん先輩

アクセストークンを生成するプログラム

<?php
define('CLIENT_ID','{ペイパルの管理画面のクライアントID}');
define('APP_SECRET','{ペイパルの管理画面のシークレット}');
define('base','https://api-m.sandbox.paypal.com');

function generateAccessToken() {
  $url = base.'/v1/oauth2/token';
  $auth = base64_encode(CLIENT_ID.':'.APP_SECRET);

  $header = [
    "Authorization: Basic {$auth}",
  ];

  $context = [
    'http' => [
      'method'  => 'POST',
      'header'  => implode("\r\n",$header),
      'content' => 'grant_type=client_credentials',
      'timeout' => 60, //second
    ],
  ];

  $json = file_get_contents($url,false,stream_context_create($context));
  return json_decode($json)?->access_token;
}

※sandbox用です。

generateAccessToken関数を実行してみましょう。

echo generateAccessToken();

createOrder関数

function createOrder() {
  $accessToken = generateAccessToken();
  $url = base.'/v2/checkout/orders';

  $header = [
    'Content-Type: application/json',
    "Authorization: Bearer {$accessToken}",
  ];

  $content = [
    'intent' => 'CAPTURE',
    'purchase_units' => [
      [
        'amount' => [
          'currency_code' => 'JPY',
          'value' => '1100',
        ],
      ],
    ],
  ];

  $context = [
    'http' => [
      'method'  => 'POST',
      'header'  => implode("\r\n",$header),
      'content' => json_encode($content),
      'timeout' => 60, //min
    ],
  ];

  $json = file_get_contents($url,false,stream_context_create($context));
  return $json;
}

capturePayment関数

function capturePayment( $orderId ) {
  $accessToken = generateAccessToken();
  $url = base."/v2/checkout/orders/{$orderId}/capture";

  $header = [
    'Content-Type: application/json',
    "Authorization: Bearer {$accessToken}",
  ];

  $context = [
    'http' => [
      'method'  => 'POST',
      'header'  => implode("\r\n",$header),
      'timeout' => 60, //min
    ],
  ];

  $json = file_get_contents($url,false,stream_context_create($context));
  return $json;
}

まとめると↓こんな感じです。file_get_contents に例外処理を追加して post関数 にまとめました。

<?php
define('CLIENT_ID','{ペイパルの管理画面のクライアントID}');
define('APP_SECRET','{ペイパルの管理画面のシークレット}');
define('base','https://api-m.sandbox.paypal.com');

function post($url,$context) {
  $result = file_get_contents($url,false,stream_context_create($context));
  $status = $http_response_header[0] ?? '';
  if (!(str_contains($status,'200 OK') || str_contains($status,'201 Created'))) {
    throw new Exception($status);
  }
  return $result;
}

function generateAccessToken() {
  $url = base.'/v1/oauth2/token';
  $auth = base64_encode(CLIENT_ID.':'.APP_SECRET);

  $header = [
    "Authorization: Basic {$auth}",
  ];

  $context = [
    'http' => [
      'method'  => 'POST',
      'header'  => implode("\r\n",$header),
      'content' => 'grant_type=client_credentials',
      'timeout' => 60, //min
    ],
  ];

  $json = post($url,$context);
  return json_decode($json)?->access_token;
}

function createOrder() {
  $accessToken = generateAccessToken();
  $url = base.'/v2/checkout/orders';

  $header = [
    'Content-Type: application/json',
    "Authorization: Bearer {$accessToken}",
  ];

  $content = [
    'intent' => 'CAPTURE',
    'purchase_units' => [
      [
        'amount' => [
          'currency_code' => 'JPY',
          'value' => '1100',
        ],
      ],
    ],
  ];

  $context = [
    'http' => [
      'method'  => 'POST',
      'header'  => implode("\r\n",$header),
      'content' => json_encode($content),
      'timeout' => 60, //min
    ],
  ];

  $json = post($url,$context);
  return $json;
}

function capturePayment( $orderID ) {
  $accessToken = generateAccessToken();
  $url = base."/v2/checkout/orders/{$orderID}/capture";

  $header = [
    'Content-Type: application/json',
    "Authorization: Bearer {$accessToken}",
  ];

  $context = [
    'http' => [
      'method'  => 'POST',
      'header'  => implode("\r\n",$header),
      'timeout' => 60, //min
    ],
  ];

  $json = post($url,$context);
  return $json;
}

パラメーターで createOrder と capturePayment を処理するようにしました。

<?php
include "paypal-api.php";

if (isset($_GET['createOrder'])) {
  header('Content-Type: application/json');
  echo createOrder();
}
if (isset($_GET['capturePayment'])) {
  header('Content-Type: application/json');
  $body = file_get_contents('php://input');
  $req = json_decode($body);
  echo capturePayment( $req->orderID );
}

クライアント側の JavaScript はこんな感じですね。

<!-- Replace "test" with your own sandbox Business account app client ID -->
<script src="https://www.paypal.com/sdk/js?client-id={ペイパルの管理画面のクライアントID}¤cy=JPY"></script>
<!-- Set up a container element for the button -->
<div id="paypal-button-container"></div>
<script>
  paypal.Buttons({
    // Order is created on the server and the order id is returned
    createOrder() {
      return fetch("/my-server/create-paypal-order", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        // use the "body" param to optionally pass additional order information
        // like product skus and quantities
        body: JSON.stringify({
          cart: [
            {
              sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
              quantity: "YOUR_PRODUCT_QUANTITY",
            },
          ],
        }),
      })
      .then((response) => response.json())
      .then((order) => order.id);
    },
    // Finalize the transaction on the server after payer approval
    onApprove(data) {
      return fetch("/my-server/capture-paypal-order", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          orderID: data.orderID
        })
      })
      .then((response) => response.json())
      .then((orderData) => {
      // Successful capture! For dev/demo purposes:
        console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
        const transaction = orderData.purchase_units[0].payments.captures[0];
        alert(`Transaction ${transaction.status}: ${transaction.id}\n\nSee console for all available details`);
        // When ready to go live, remove the alert and show a success message within this page. For example:
        // const element = document.getElementById('paypal-button-container');
        // element.innerHTML = '<h3>Thank you for your payment!</h3>';
        // Or go to another URL:  window.location.href = 'thank_you.html';
      });
    }
  }).render('#paypal-button-container');
</script>

注文情報取得

注文を取得する関数はこちらです。キーを注文番号にしてますけど、これでいいのかな?
※orderID は「取引ID」ではありません。取得方法も不明。注文時のIDを保存しておくしかない?

function getOrder( $orderID ) {
  $accessToken = generateAccessToken();
  $url = base.'/v2/checkout/orders/'.$orderID;

  $header = [
    "Authorization: Bearer {$accessToken}",
  ];

  $context = [
    'http' => [
      'method'  => 'GET',
      'header'  => implode("\r\n",$header),
      'timeout' => 60, //min
    ],
  ];

  $json = post($url,$context);
  return $json;
}

CAPTURE

CAPTURE の明細をする例です。

$content = [
  'intent' => 'CAPTURE',
  'purchase_units' => [
    [
      'items' => [
        [
          'name' => '{商品名}',
          'quantity' => '{注文個数}',
          'sku' => '{商品SKU}',
          'unit_amount' => ['currency_code'=>'JPY','value'=>{商品価格}],
          'tax' => ['currency_code'=>'JPY','value'=>{商品消費税}],
        ],
      ],
      'amount' => [
        'currency_code' => 'JPY',
        'value' => $bsk_cnf['pay_all'],
        'breakdown' => [
          'item_total' => ['currency_code'=>'JPY','value'=>{商品小計}],
          'tax_total' => ['currency_code'=>'JPY','value'=>{消費税}],
          'discount'   => ['currency_code'=>'JPY','value'=>{値引き}],
          'shipping'   => ['currency_code'=>'JPY','value'=>{送料}],
        ],
      ],
    ],
  ],
];

以上

Scroll to Top