![見出し画像](https://assets.st-note.com/production/uploads/images/172317878/rectangle_large_type_2_efa7d0f3e47ef63e643e3aa96dee3a66.png?width=1200)
LaravelプロジェクトにPaypalサブスクを導入する
まえがき
コロナ禍時代に一気に認知度が高まった定額課金型のサブスクリプション。これを導入するサービスがオンライン界オフライン界問わずかなり増えました。
一方で、1サービス1サービス毎の定額料金は少額だが複数のサービスに跨って契約していると総額の毎月費用がかなり圧迫されてしまうことから、ここ1年くらいはAWSのような従量課金型サービスが徐々に目立ってきました。
ここからも分かるように、サブスクリプション(以下、サブスク)は事業やサービスによって合う合わないがあることが言えます。とはいえ、サブスクは収入の安定化をもたらし、先行きが不透明になりがちな中小零細企業・個人事業主(以下、小規模事業者)にとって大変ありがたい仕組みです。日本だけみても様々なサブスク決済代行会社が存在しているように、まだまだ需要がある徴収システムです。
個人でも使えるサブスクシステムにはfincodeやStripe、PayPalなど様々ありますが、本稿ではPayPalを取り上げます。
近年クレジットカードの不正使用が問題視されていることを背景に各クレジットカード会社を筆頭に引き締めが強化されています。それに伴い、これまでは問題なく提携できていたサービスでもいつの間にか禁止制限業種に含まれたり定期的なクレジットカード会社の再審査で落とされたりで急にサブスク決済サービスが使えなくなるという事態も出てきました。
そもそもそんな際どいサービスを展開するなよという声も聞こえてきそうですが、意外と小規模事業者はそういった大手が相手にしないニッチな分野を責めることで生き残る可能性をグッと押し上げているという生命線にもなっているので一概に批判はできないところですが、兎にも角にも事業者にとってはそんな急に停止されたらたまったものではありません。
その点PayPalは海外会社ということもあり、日本に本社を置く彼らよりも比較的基準が緩い部分もあります。PayPalはまだまだ私たち小規模事業者の味方でいるので、PayPalのサブスク機能をLaravelプロジェクトに実装してみようと思います。
※基本的には公式が指示している手順で進めていきます。
売り手のサブスクリプションに関するよくあるご質問
手順1.サブスクリプションプランを作る
https://www.paypal.com/billing/subscriptions にアクセスし、プランの作成ボタンを押します。
![](https://assets.st-note.com/img/1738240539-UG9pmtAuZKnCi76RXQBsHhq2.png?width=1200)
サブスクリプションを提携する先のサービスに関する情報を入力します。
![](https://assets.st-note.com/img/1738240602-AET2D6Z3df1HtsxKgX7VbyUN.png?width=1200)
次に、徴収体系を選びます。毎月同じ額を徴収したい場合は「固定料金設定」を選択して”次へ”を押します。
![](https://assets.st-note.com/img/1738240846-Wh3VHXPJqaI0lCEDor8OpZRT.png?width=1200)
次に、プラン名を定義します。
![](https://assets.st-note.com/img/1738240989-xtNUHjWOyeTJciFofz5n9qsk.png?width=1200)
次に、料金設定を定義します。
![](https://assets.st-note.com/img/1738241053-4nq6KNTjHcCUbd8BPRWasYe1.png)
通貨・・・請求する通貨を設定します。
料金設定・・・事務手数料など初回のみ発生する料金があるなら選択します。お試し期間がある場合は選択します。
購読機関・・・サービスが続く限り徴収したい場合は”無制限の請求サイクル”を選択し、徴収回数を設けたい場合は”制限された請求サイクル”を選択します。
金額・・・毎月徴収するサービスの利用料金を記入します。
このサブスクリプションプランの税金を計算する・・・税込みにするか税別にするか、そもそも税金は計算しないかを指定します。
未払い支払いの自動請求をオンにする・・・例えば月額1000円のサービスがあったとする。もし顧客が、1月にクレジットカードの上限枠がカツカツで1000円が決済できなかった場合、2月に2000円を徴収するか、通常の1000円を徴収するかを指定します。
手順2.作成したプランのHTMLコードを実装する
確認画面で問題なければ”プランをオンにする”を押します。すると下記図のように決済画面のレイアウト設定が出るので、お好きなように調整します。
![](https://assets.st-note.com/img/1738241566-L6D714gYMaWnOtzuGkolrVme.png?width=1200)
決済ボタンはカスタマイズで複数配置できるようです。下記技術者向けドキュメントにあるので、カスタマイズしたい場合は一度参照してみてください。
https://developer.paypal.com/docs/subscriptions/?_ga=2.243596237.977753672.1738240578-1507756479.1738238614
レイアウト調整が終わったら”コードをコピー”ボタンを押します。コピーされたHTMLの例は以下の通りです。
<div id="paypal-button-container-P-xxxxxxxxxxxxxxxxxxxxxxx"></div>
<script src="https://www.paypal.com/sdk/js?xxxxxxxxxxxxxx" data-sdk-integration-source="button-factory"></script>
<script>
paypal.Buttons({
style: {
shape: 'pill',
color: 'gold',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function(data, actions) {
return actions.subscription.create({
/* Creates the subscription */
plan_id: 'P-xxxxxxxxxxxxxxxxxxx'
});
},
onApprove: function(data, actions) {
alert(data.subscriptionID); // You can add optional success message for the subscriber here
}
}).render('#paypal-button-container-P-xxxxxxxxxxxxxxxxxxx'); // Renders the PayPal button
</script>
コードをコピーしたら緑枠のブロックが出てくるのでクリックすると、そのHTMLコードをどのように実装したらいいかが分かります。
![](https://assets.st-note.com/img/1738245270-AupP536Fjzx0HykJYbfGBU1E.png?width=1200)
やることは単純で、Laravel側のviewファイルに↑でコピーしたHTMLコードを貼り付けるだけでOKです。
<?php
class IPN
{
//メンバー
public $pdo;
//コンストラクタ
public function __construct(){
}
function connectDB() {
$iniArray = parse_ini_file("../imagegetter/lib/config.ini", true);
$host = $iniArray['db']['host'];
$dbname = $iniArray['db']['dbName'];
$user = $iniArray['db']['user'];
$password = $iniArray['db']['password'];
try {
$this->pdo = new PDO('mysql:host='.$host.';dbname='.$dbname.';charset=utf8',$user,$password,
array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
));
} catch (PDOException $e) {
die('データベース接続失敗。'.$e->getMessage());
}
}
// 取得
function getUser($email, $password){
$password = hash('sha256', $password);
$stmt = $this->pdo->prepare("SELECT * FROM users WHERE email = :email AND password = :password");
$stmt->bindParam(':email', $email, PDO::PARAM_STR);
$stmt->bindParam(':password', $password, PDO::PARAM_STR);
$stmt->execute();
return $stmt->fetch();
}
function getActiveUser($email, $password){
$password = hash('sha256', $password);
$stmt = $this->pdo->prepare("SELECT * FROM users WHERE email = :email AND password = :password AND unsubscribed = 0 AND active_member = 1");
$stmt->bindParam(':email', $email, PDO::PARAM_STR);
$stmt->bindParam(':password', $password, PDO::PARAM_STR);
$stmt->execute();
return $stmt->fetch();
}
function getUserById($id){
$stmt = $this->pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetch();
}
// 作成
function createUser($email, $password, $piId){
$password = hash('sha256', $password);
$this->pdo->beginTransaction();
$stmt = $this->pdo->prepare("INSERT INTO users (email, password, piId) VALUES (:email, :password, :piId)");
$stmt->bindParam(':email', $email, PDO::PARAM_STR);
$stmt->bindParam(':password', $password, PDO::PARAM_STR);
$stmt->bindParam(':piId', $piId, PDO::PARAM_INT);
$stmt->execute();
$lastId = $this->pdo->lastInsertId('id');
$this->pdo->commit();
return $lastId;
}
function updateUserActiveStatus($id, $flag){
$stmt = $this->pdo->prepare("UPDATE users SET active_member = :flag WHERE id = :id");
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->bindParam(':flag', $flag, PDO::PARAM_INT);
$stmt->execute();
}
function updateUserUnsubscribedStatus($id, $flag){
$stmt = $this->pdo->prepare("UPDATE users SET unsubscribed = :flag WHERE id = :id");
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->bindParam(':flag', $flag, PDO::PARAM_INT);
$stmt->execute();
}
function listUsers(){
$stmt = $this->pdo->prepare("SELECT id, email, created_time, active_member, unsubscribed FROM users ORDER BY created_time DESC");
$stmt->execute();
$output = array();
while($row = $stmt -> fetch(PDO::FETCH_ASSOC)) {
array_push($output, $row);
}
return $output;
}
//insert paypal data
function ppdataRequest($runRequest){
$this->pdo->beginTransaction();
$stmt = $this->pdo->prepare("INSERT INTO ppdata (runRequest) VALUES (:runRequest)");
$stmt->bindParam(':runRequest', $runRequest, PDO::PARAM_STR);
$stmt->execute();
$lastId = $this->pdo->lastInsertId('id');
$this->pdo->commit();
return $lastId;
}
//insert paypal data会員登録
function ppUserRegister($pe, $in, $pr, $ti){
$this->pdo->beginTransaction();
$stmt = $this->pdo->prepare("INSERT INTO paymentInfo (payerEmail, itemNumber, price, payId)
VALUES (:payerEmail, :itemNumber, :price, :payId)");
$stmt->bindParam(':payerEmail', $pe, PDO::PARAM_STR);
$stmt->bindParam(':itemNumber', $in, PDO::PARAM_STR);
$stmt->bindParam(':price' , $pr, PDO::PARAM_INT);
$stmt->bindParam(':payId' , $ti, PDO::PARAM_STR);
$stmt->execute();
$lastId = $this->pdo->lastInsertId('id');
$this->pdo->commit();
return $lastId;
}
//支払いテーブルからpiIdを取得
function getpiId($payerEmail, $payId){
$stmt = $this->pdo->prepare("SELECT * FROM paymentInfo WHERE payerEmail = :payerEmail AND payId = :payId");
$stmt->bindParam(':payerEmail', $payerEmail, PDO::PARAM_STR);
$stmt->bindParam(':payId' , $payId , PDO::PARAM_STR);
$stmt->execute();
return $stmt->fetch();
}
//キャンセル時のログイン不可情報更新
function updateActiveUserOff($piId){
$stmt = $this->pdo->prepare("UPDATE users SET active_member = 0 WHERE piId = :piId");
$stmt->bindParam(':piId', $piId, PDO::PARAM_INT);
$stmt->execute();
}
//20.03.05追加
function sbscrKind($subscribeType, $payment_status){
}
}
?>