ãã®èšäºã¯ãäž»ã«ãã®ã·ã¹ãã ã䜿çšããããšããªã人ã«çŠç¹ãåœãŠãŠããŸãã Paypalã®å°é家ãããã§èªåèªèº«ã§æ°ãããã®ãèŠã€ããããšã¯ãŸããããŸããã ããããããããã圌ãã¯ãã®æ¹æ³ã®çæãææããããã©ã®ããã«ç°ãªãæ¹æ³ã§å®è£ ã§ããã®ããã¢ããã€ã¹ããã§ãããã
ã¢ã«ãŠã³ãäœæ
ãã®ã¹ããŒã ãå®è£ ããã«ã¯ãããžãã¹ã¢ã«ãŠã³ããå¿ èŠã§ãã PayPal Payments Standardã§ååã§ãã
ãªã³ã¯ã«åŸã£ãŠã¢ã«ãŠã³ããäœæããŸãã
ãµã³ãããã¯ã¹ã¢ã«ãŠã³ãã®äœæ
Paypal Sandboxã䜿çšããŠãã¢ããªã±ãŒã·ã§ã³ããã¹ãããŸãã 2ã€ã®ãµã³ãããã¯ã¹ã¢ã«ãŠã³ããå¿ èŠã§ãã ãã€ã€ãŒã¢ã«ãŠã³ãïŒãã€ã€ãŒïŒãšã»ã©ãŒã¢ã«ãŠã³ãïŒãã¡ã·ãªããŒã¿ãŒïŒã ãŸããäž¡æ¹ã®ãµã³ãããã¯ã¹ã¢ã«ãŠã³ãã«ãã¹ã¯ãŒããèšå®ããå¿ èŠããããŸãã ãããè¡ãã«ã¯ãéçºè ã»ã¯ã·ã§ã³ã® paypalãŠã§ããµã€ãã«ã¢ã¯ã»ã¹ããŠãã ãã ã ãã°ã€ã³ããŠã ããã·ã¥ããŒãã«ç§»åããŸãã å·ŠåŽã®ã¡ãã¥ãŒã«ã¯ã[ãµã³ãããã¯ã¹]ã»ã¯ã·ã§ã³ã®[ã¢ã«ãŠã³ã]ã¿ãããããŸãã ããã§ã¯ã2ã€ã®ãµã³ãããã¯ã¹ã¢ã«ãŠã³ãïŒBuyerãšFacilitatorïŒãèŠãããšãã§ããŸãã
ãããã¡ã€ã«ãã¯ãªãã¯ãã衚瀺ãããã¢ãŒãã«ãŠã£ã³ããŠã§[ãã¹ã¯ãŒãã®å€æŽ]ãã¯ãªãã¯ãããã¹ã¯ãŒããä¿åããŸãã
äž¡æ¹ã®ã¢ã«ãŠã³ãã«ãã¹ã¯ãŒããèšå®ããŸãã ãã®åŸã Paypal Sandbox Webãµã€ãã«ã¢ã¯ã»ã¹ããŠããã°ã€ã³ããŠã¿ãŠãã ããã
Paypalã®ã»ããã¢ãã
次ã«ãè³éãåãåãPaypal Facilitatorã¢ã«ãŠã³ããèšå®ããå¿ èŠããããŸãã Sandbox Webãµã€ãã«ã¢ã¯ã»ã¹ãããã¡ã·ãªããŒã¿ãŒã¢ã«ãŠã³ãã䜿çšããŠãã°ã€ã³ãããããã¡ã€ã«èšå®ã«ã¢ã¯ã»ã¹ããŸãã ãããã¡ã€ã«ã¡ãã¥ãŒãéãã販売ããŒã«ã®ã¢ã€ãã ãéžæããŸãã
[ãªã³ã©ã€ã³è²©å£²]ã»ã¯ã·ã§ã³ã§ã[ãŠã§ããµã€ãã®èšå®]ãéžæãã[æŽæ°]ãã¯ãªãã¯ããŸãã ããã§ããŠãŒã¶ãŒã®ãªãã€ã¬ã¯ããæå¹ã«ã§ããŸãã æ¯æããå®äºãããšããŠãŒã¶ãŒã¯ããã©ã«ãã§æå®ãããURLã«ãªãã€ã¬ã¯ããããŸãã ãã ãããŠãŒã¶ãŒãå¥ã®URLã«ãªãã€ã¬ã¯ãããããšãã§ããŸãïŒä»¥äžãåç §ïŒã
ãŸããPaypalã€ã³ã¹ã¿ã³ãæ¯æãéç¥ãã¢ã¯ãã£ãã«ããå¿ èŠããããŸãã ãããè¡ãã«ã¯ããæ¯æãã®ååŸãšãªã¹ã¯ã®ç®¡çãã»ã¯ã·ã§ã³ã§ããå³ææ¯æãéç¥ãé ç®ãéžæãããæŽæ°ããã¯ãªãã¯ããŸãã
IPNèšå®ã§ãIPNãªã¹ããŒãæ©èœããURLãæå®ããŸãã ãã®URLã¯ã°ããŒãã«ã«ã¢ã¯ã»ã¹å¯èœã§ããå¿ èŠããããŸã æäœã®éç¥ãåãåããŸãã
ã¡ãã»ãŒãžé ä¿¡ããªã³ã«ããŠä¿åããŸãã ããã§ã¢ã«ãŠã³ãã®ã»ããã¢ãããå®äºããŸããã æ¯æãã®èšå®ãçŽæ¥éå§ã§ããŸãã
äžåæã
ãŸãã1åéãã®æ¯æããè¡ããŸãã ããã¯ããããæãäžè¬çãªäœ¿çšäŸã§ãã ãŠãŒã¶ãŒã¯ã補åãŸãã¯1åéãã®ãµãŒãã¹ãè³Œå ¥ãããã ãã§ãã ãŸããç§ã¯ãã€ãã«ã®èšå®ã§äœãå€æŽããå¿ èŠããããªãããšãæã¿ãŸãã ååãšäŸ¡æ Œã®ãªã¹ãã¯ã¢ããªã±ãŒã·ã§ã³ã®ããŒã¿ããŒã¹ã«ä¿åãããŸãããå¿ èŠã«å¿ããŠå€æŽã§ããŸãã 1åéãã®æ¯æãã«ã¯ã æ¯æããã¿ã³ïŒPayPal Payments StandardïŒã䜿çšããŸãã
ããŒã¿æ§é
ååã®ãªã¹ãã¯ãã¢ããªã±ãŒã·ã§ã³ã®ããŒã¿ããŒã¹ã«ä¿åãããŸãã 補åã¯ãã€ã§ãè¿œå ããã³åé€ããã³ç·šéã§ããŸãã ããã§ã¯æãåçŽãªæ§é ã瀺ãããŠããããã¹ãŠã®æ å ±ã1ã€ã®ããŒãã«ã«ä¿åãããŠããŸãã
ãã ããã¿ã¹ã¯ãè€éã«ããããšãã§ããŸãã ããšãã°ã泚æããååã®æ°éã«å¿ããŠäŸ¡æ Œãå€æŽããããææ¥ãšæéã«å¿ããŠäŸ¡æ Œãå€æŽãããããŸãã
ãŸãã¯ã泚æã«å€ãã®ç°ãªã補åãå«ããŸãã
補å-ããã§ååãä¿ç®¡ããŸãïŒ
id | ãåå | äŸ¡æ Œ | 説æ |
1 | 補å1 | 1.0 | ... |
2 | 補å2 | 4.0 | ... |
ãŠãŒã¶ãŒ-ããã«ãŠãŒã¶ãŒãä¿åããŸãïŒ
id | å | å§ | ã¡ãŒã« | ãã¹ã¯ãŒã |
315 | ã¢ã©ã³ | ã¹ãã¹ | alansmith@example.com | $ 1 $ 2z4.hu5ã$ E3A3H6csEPDBoH8VYK3AB0 |
316 | ãžã§ãŒ | ã㊠| joedoe@example.com | $ 1 $ Kd4.Lf0ã$ PGc1h7vwmy9N6EJxac953 / |
products_users-çºéå ïŒ
id | user_id | product_id | items_count | created_date |
1 | 315 | 1 | 3 | 2015-09-03 08:23:05 |
ãŸãããã©ã³ã¶ã¯ã·ã§ã³å±¥æŽãããŒã¿ããŒã¹ã®ãã©ã³ã¶ã¯ã·ã§ã³ããŒãã«ã«ä¿åããŸãã
txn_id | txn_type | mc_gross | mc_currency | é | æ¯ææ¥ | payment_status | äºæ¥ | receiver_email | payer_id | payer_email | relation_id | relation_type | created_date |
ãæ¯æãæ¹æ³
ãŸãã泚æãã©ãŒã ãäœæããŸãã ã¢ããªã±ãŒã·ã§ã³ã§ãã©ãŒã ãçæãã泚æã®äž»ãªãã©ã¡ãŒã¿ãŒïŒè£œååãäŸ¡æ Œãæ°éïŒãæå®ããŸãã
ããã§ãäŸ¡æ Œãååãæ°éãªã©ãæå®ã§ããŸãã ã«ã¹ã¿ã ãã£ãŒã«ãã¯ãä»»æã®ããŒã¿ã転éã§ãããšããç¹ã§äŸ¿å©ã§ãã ããã§ã¯ã補åIDããŠãŒã¶ãŒIDãããã³ãã®ä»ã®æ å ±ãæž¡ããŸãã ä»åŸã®æ¯æãåŠçã®ããã«ãããã®ããŒã¿ãå¿ èŠã«ãªããŸãã
è€æ°ã®ãã©ã¡ãŒã¿ãŒãæž¡ãå¿ èŠãããå Žåã¯ãjsonãŸãã¯ã·ãªã¢ã«åã䜿çšã§ããŸãã ãŸãã¯ãon0ãon1ãos0ãos1ã®åœ¢åŒã®è¿œå ãã£ãŒã«ãã䜿çšã§ããŸãã å人çã«ãç§ã¯ããããã§ãã¯ããŸããã§ãããç§ã¯ããã§æ å ±ãèŠã€ããŸããã
以äžã¯ãã©ãŒã ã®äŸã§ãïŒ
<?php $payNowButtonUrl = 'https://www.sandbox.paypal.com/cgi-bin/websc'; $userId = 315 // id $receiverEmail = 'xxx-facilitator@yandex.ru'; //email ( paypal ) $productId = 1; $itemName = 'Product 1'; // $amount = '1.0'; // ( 1 .) $quantity = 3; // $returnUrl = 'http://your-site.com/single_payment?status=paymentSuccess'; $customData = ['user_id' => $userId, 'product_id' => $productId]; ?> <form action="<?php echo $payNowButtonUrl; ?>" method="post"> <input type="hidden" name="cmd" value="_xclick"> <input type="hidden" name="business" value="<?php echo $receiverEmail; ?>"> <input id="paypalItemName" type="hidden" name="item_name" value="<?php echo $itemName; ?>"> <input id="paypalQuantity" type="hidden" name="quantity" value="<?php echo $quantity; ?>"> <input id="paypalAmmount" type="hidden" name="amount" value="<?php echo $amount; ?>"> <input type="hidden" name="no_shipping" value="1"> <input type="hidden" name="return" value="<?php echo $returnUrl; ?>"> <input type="hidden" name="custom" value="<?php echo json_encode($customData);?>"> <input type="hidden" name="currency_code" value="USD"> <input type="hidden" name="lc" value="US"> <input type="hidden" name="bn" value="PP-BuyNowBF"> <button type="submit"> Pay Now </button> </form>
å®éããã©ã¡ãŒã¿ãŒã¯ãã£ãšå€§ããããããšãã§ãã詳现ãªæ å ±ã¯ããã¥ã¡ã³ãã«ãããŸã ã ãã©ãŒã ãéä¿¡ãããšããŠãŒã¶ãŒã¯ãã€ãã«æ¯æãããŒãžã«ç§»åãã泚æã®è©³çŽ°ãåã³è¡šç€ºãããŸãã
ããã§ããŠãŒã¶ãŒã¯ãPayPalã¢ã«ãŠã³ããŸãã¯éè¡ã«ãŒãã䜿çšããŠæ³šæã®ä»£éãæ¯æãããšãã§ããŸãã ãã®åŸããŠãŒã¶ãŒã¯åœç€Ÿã®Webãµã€ãïŒãªãã€ã¬ã¯ããã©ã¡ãŒã¿ãŒïŒã«ãªãã€ã¬ã¯ããããããã§æ¯æããåŠçãããŠããããšãéç¥ã§ããŸãã
å³ææ¯æãéç¥ïŒIPNïŒ
ãŠãŒã¶ãŒãæ¯æããè¡ã£ãåŸãPaypalã¯ãããåŠçããã¢ããªã±ãŒã·ã§ã³ã«ç¢ºèªãéä¿¡ããŸãã ãããè¡ãã«ã¯ã å³ææ¯æãéç¥ïŒIPNïŒãµãŒãã¹ã䜿çšããŸãã
èšäºã®åé ã§ãPaypalã¢ã«ãŠã³ããèšå®ããIPNéç¥URLãèšå®ããŸãã ããã§ãIPNèŠæ±ãåŠçããIPNãªã¹ããŒãäœæããŸãã Paypalã¯IPNãªã¹ããŒã®å®è£ äŸãæäŸããŸãã ãµãŒãã¹ã®è©³çŽ°ãªèª¬æã¯ããã§èŠã€ããããšãã§ããŸã ã èŠããã«ãPaypalã¯ãŠãŒã¶ãŒã®æ¯æããåŠçãããã¹ãŠãæ£åžžã§ãããæ¯æããæ£åžžã«å®äºããããšã確èªããŸãã ãã®åŸãIPNã¯Postãšãããã©ãŒã ã®éç¥URLã«ãªã¯ãšã¹ããéä¿¡ããŸãã
mc_gross=37.50&protection_eligibility=Ineligible&payer_id=J86MHHMUDEHZU&tax=0.00&payment_date=07%3A04%3A48+Mar+30%2C+2015+PDT&payment_status=Completed&charset=windows-1252&first_name=test&mc_fee=1.39¬ify_version=3.8&custom=%7B%22user_id%22%3A314%2C%22service_provider%22%3A%22twilio%22%2C%22service_name%22%3A%22textMessages%22%7D&payer_status=verified&business=antonshel-facilitator%40gmail.com&quantity=150&verify_sign=AR-ITpb83c-ktcbmApqG4jM17OeQAx2RSvfYZo4XU8YFZrTSeF.iYsSx&payer_email=antonshel-buyer%40gmail.com&txn_id=30R69966SH780054J&payment_type=instant&last_name=buyer&receiver_email=antonshel-facilitator%40gmail.com&payment_fee=1.39&receiver_id=VM2QHCE6FBR3N&txn_type=web_accept&item_name=GetScorecard+Text+Messages&mc_currency=USD&item_number=&residence_country=US&test_ipn=1&handling_amount=0.00&transaction_subject=%7B%22user_id%22%3A314%2C%22service_provider%22%3A%22twilio%22%2C%22service_name%22%3A%22textMessages%22%7D&payment_gross=37.50&shipping=0.00&ipn_track_id=6b01a2c76197
IPNãªã¹ããŒã¯ãã®ãªã¯ãšã¹ããåŠçããå¿ èŠããããŸãã ç¹ã«ïŒ
- ãªã¯ãšã¹ãã®çš®é¡ïŒ1åéãã®æ¯æããŸãã¯å®æè³Œå ¥ïŒã確èªããŸãã ããã«å¿ããŠãåŠçæ¹æ³ãç°ãªããŸãã ãã®å Žåã1åéãã®æ¯æã-web_acceptã«ãªããŸãã
- ç°å¢ãéžæããŸã-ãµã³ãããã¯ã¹ãŸãã¯ã©ã€ãã
- èŠæ±ã®æå¹æ§ã確èªããŠãã ããã IPNãªã¯ãšã¹ããã©ã®ããã«èŠããããIPNéç¥URLãç¥ã£ãŠããã°ã誰ã§ãåœã®ãªã¯ãšã¹ããéä¿¡ã§ããŸãã ãããã£ãŠããã®ãã§ãã¯ãè¡ãå¿ èŠããããŸãã
<?php /** * Class PaypalIpn */ class PaypalIpn{ private $debug = true; private $service; /** * @throws Exception */ public function createIpnListener(){ $postData = file_get_contents('php://input'); $transactionType = $this->getPaymentType($postData); $config = Config::get(); // if($transactionType == PaypalTransactionType::TRANSACTION_TYPE_SINGLE_PAY){ $this->service = new PaypalSinglePayment(); } elseif($transactionType == PaypalTransactionType::TRANSACTION_TYPE_SUBSCRIPTION){ $this->service = new PaypalSubscription($config); } else{ throw new Exception('Wrong payment type'); } $raw_post_data = file_get_contents('php://input'); $raw_post_array = explode('&', $raw_post_data); $myPost = array(); foreach ($raw_post_array as $keyval) { $keyval = explode ('=', $keyval); if (count($keyval) == 2) $myPost[$keyval[0]] = urldecode($keyval[1]); } $customData = $customData = json_decode($myPost['custom'],true); $userId = $customData['user_id']; // read the post from PayPal system and add 'cmd' $req = 'cmd=_notify-validate'; if(function_exists('get_magic_quotes_gpc')) { $get_magic_quotes_exists = true; } else{ $get_magic_quotes_exists = false; } foreach ($myPost as $key => $value) { if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) { $value = urlencode(stripslashes($value)); } else { $value = urlencode($value); } $req .= "&$key=$value"; } $myPost['customData'] = $customData; $paypal_url = 'https://www.sandbox.paypal.com/cgi-bin/websc'; //$paypal_url = 'https://www.paypal.com/cgi-bin/websc'; // IPN $res = $this->sendRequest($paypal_url,$req); // Inspect IPN validation result and act accordingly // Split response headers and payload, a better way for strcmp $tokens = explode("\r\n\r\n", trim($res)); $res = trim(end($tokens)); /**/ if (strcmp ($res, "VERIFIED") == 0) { // $this->service->processPayment($myPost); } else if (strcmp ($res, "INVALID") == 0) { // self::log([ 'message' => "Invalid IPN: $req" . PHP_EOL, 'level' => self::LOG_LEVEL_ERROR ], $myPost); } /**/ } private function sendRequest($paypal_url,$req){ $debug = $this->debug; $ch = curl_init($paypal_url); if ($ch == FALSE) { return FALSE; } curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_POSTFIELDS, $req); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_FORBID_REUSE, 1); if($debug == true) { curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLINFO_HEADER_OUT, 1); } curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); // , User-Agent - . live curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close', 'User-Agent: ' . $this->projectName)); $res = curl_exec($ch); curl_close($ch); return $res; } public function getPaymentType($rawPostData){ $post = $this->getPostFromRawData($rawPostData); if(isset($post['subscr_id'])){ return "subscr_payment"; } else{ return "web_accept"; } } /** * @param $raw_post_data * @return array */ public function getPostFromRawData($raw_post_data){ $raw_post_array = explode('&', $raw_post_data); $myPost = array(); foreach ($raw_post_array as $keyval) { $keyval = explode ('=', $keyval); if(count($keyval) == 2) $myPost[$keyval[0]] = urldecode($keyval[1]); } return $myPost; } } ?>
ãã®åŸãPaypalããªã¯ãšã¹ãã®çæ£æ§ã確èªããå Žåãããã«åŠçãé²ããããšãã§ããŸãã
æ¯æãåŠç
ãŸããã«ã¹ã¿ã ãã£ãŒã«ãã®å€ãååŸããå¿ èŠããããŸããã«ã¹ã¿ã ãã£ãŒã«ãã«ã¯ã泚æIDããŠãŒã¶ãŒIDããŸãã¯ãã®ä»ã®ãã®ïŒã¢ããªã±ãŒã·ã§ã³ã®ããžãã¯ã«ãã£ãŠç°ãªããŸãïŒãæž¡ããŸãã ãããã£ãŠãããŒã¿ããŒã¹ãããŠãŒã¶ãŒ/泚ææ å ±ãååŸã§ããŸãã ãã©ã³ã¶ã¯ã·ã§ã³IDãååŸããå¿ èŠããããŸãã
Paypalã¯ãåãååŒã®ç¢ºèªãæ°åéä¿¡ã§ããŸãã ãããã£ãŠã確èªããå¿ èŠãããããã©ã³ã¶ã¯ã·ã§ã³ãåŠçãããªãã£ãå Žåã¯åŠçããŸãã ãã©ã³ã¶ã¯ã·ã§ã³ãæ¢ã«åŠçãããŠããå ŽåãäœãããŸããã
æ¯æããæ€èšŒããŸãã ãã¹ãŠãæ£åžžã§ããã°ãæ¯æãæ å ±ãããŒã¿ããŒã¹ã«ä¿åããããã«ã¢ã¯ã·ã§ã³ãå®è¡ã§ããŸãïŒãŠãŒã¶ãŒã«ããã¬ãã¢ã ãã¹ããŒã¿ã¹ãå²ãåœãŠã泚æã¹ããŒã¿ã¹ããæ¯æãæžã¿ããªã©ïŒã æ¯æããæ€èšŒãããŠããªãå Žåã¯ãçç±ã確èªããŠãŠãŒã¶ãŒã«é£çµ¡ããå¿ èŠããããŸãã ãããªãæäœãç¹ã«æ¯æãã®ãã£ã³ã»ã«ã¯ãæåã§å®è¡ãããŸãã
<?php function processPayment($myPost){ $customData = json_decode($myPost['custom'],true); $userId = $customData['user_id']; $productId = $customData['product_id']; // $userService = new UserService(); $userInfo = $userService->getUserData($userId); // $transactionService = new TransactionService(); $transaction = $transactionService->getTransactionById($myPost['txn_id']); if($transaction === null){ // $productService = new ProductService(); $product = $productService->getProductById($productId); // if($this->validateTransaction($myPost,$product)){ // . . $transactionService->createTransaction($myPost); // - } else{ // . } } else{ //, . } } ?>
æ¯æãæ€èšŒ
æ¯æãã®æ€èšŒã¯ãã¢ããªã±ãŒã·ã§ã³ã®ããžãã¹ããžãã¯ã«å€§ããäŸåããŠããŸãã ç¹å®ã®æ¡ä»¶ãè¿œå ãããå ŽåããããŸãã ããšãã°ããŠãŒã¶ãŒã¯15ãŠãããã®ååãæ¯æããŸããããå©çšã§ããã®ã¯10åã ãã§ãããã®ãããªæ³šæãèŠéãããšã¯ã§ããŸããã
ãã ãããã©ãŒã çæã®æ®µéã§ãã®ãããªããšã確èªããããšã¯çã«ããªã£ãŠããŸãã äžæ£è¡çºãé²ãããã§ã¯ãªããæ¯æãã®æ€èšŒãå¿ èŠã§ãïŒããšãã°ããŠãŒã¶ãŒãæ¯æãã®åœ¢ã§ååã®éãæåã§å¢ãããããäŸ¡æ Œã¯å€æŽããªãã£ãå ŽåïŒã
ãšã«ãããã§ãã¯ã¢ãŠããã䟡å€ã®ãããã®ãããã€ããããŸãã
- æ¯æããšããŒã¿ããŒã¹ã§äŸ¡æ Œã®å¯Ÿå¿ã確èªããŸã
- åèšã³ã¹ãã0ã«çãããªãããšã確èªããŸãïŒåã®æ®µèœã§ãã®ã±ãŒã¹ãæ±ã£ãŠãããããåŠæ³ïŒ
- æ£ããåå人ãæå®ãããŠããããšã確èªããŠãã ãã
- æ¯æãç¶æ³ã確èªãã
- æ¯æãé貚ã確èªãã
<?php function validateTransaction($myPost,$product){ $valid = true; /* * */ if($product->getTotalPrice($myPost['quantity']) != $myPost['payment_gross']){ $valid = false; } /* * */ elseif($myPost['payment_gross'] == 0){ $valid = false; } /* * */ elseif($myPost['payment_status'] !== 'Completed'){ $valid = false; } /* * */ elseif($myPost['receiver_email'] != 'YOUR PAYPAL ACCOUNT'){ $valid = false; } /* * */ elseif($myPost['mc_currency'] != 'USD'){ $valid = false; } return $valid; } ?>
ããŠããã¡ããããã§ãã¯ãè¿œå ããŸãã
ãã®çµæã1åéãã®æ¯æããæå¹ã«ãªããŸãã æ¯æããã©ãŒã ãäœæãã段éã§ããã©ã¡ãŒã¿ãŒãæå®ã§ããŸãã ããšãã°ã補åã®äŸ¡æ Œãæè»ã«å¶åŸ¡ã§ããŸãïŒ101ã®é¡§å®¢ããšã«3ã®äŸ¡æ Œã§2ã30ïŒ ã®å²åŒãªã©ïŒã Paypalã§äœããå€æŽããå¿ èŠã¯ãããŸããã
ãµãã¹ã¯ãªãã·ã§ã³
次ã«ããµãã¹ã¯ãªãã·ã§ã³ã®å®è£ ãæ€èšããŸãã ååã¯ã1åéãã®æ¯æããšåãã§ãã å®æçãªæ¯æãã®ã¿ã ãããã£ãŠããããã®å®è£ ã¯ããè€éã§ãã
ããã€ãã®æéãã©ã³ãå©çšã§ããŸããããšãã°ãç¡æ-ç¡æããã-ãŠãŒã¶ãŒãããæé¡5ãã«ããã¬ãã¢ã -ãŠãŒã¶ãŒãããæé¡10ãã«ã§ãã
ãŠãŒã¶ãŒã¯ãæªäœ¿çšæéã®æãæ»ãã§éäŒã§ããŸãã ãŸãããŠãŒã¶ãŒã¯ãå¥ã®æéãã©ã³ãžã®åãæ¿ãããŠãŒã¶ãŒæ°ã®å€æŽãªã©ããµãã¹ã¯ãªãã·ã§ã³æ¡ä»¶ãå€æŽã§ããŸãã
ç¡æ賌èªã®å ŽåãPayPalã¯ãŸã£ããå¿ èŠãªãããšã¯æããã§ãã ããããããã®æéãã©ã³ã¯ãã¢ããªã±ãŒã·ã§ã³ã«ãŠãŒã¶ãŒãç»é²ããããšããã«èªåçã«ã¢ã¯ãã£ãåãããã¯ãã§ãã ãã®ã¹ããŒã ã¯ãäžéšã®SaaSã·ã¹ãã ã®äžè¬çãªäœ¿çšæ¹æ³ã瀺ããŠãããšããç¹ã§åªããŠããŸãã å€åºå ã§ã¯ãPaypalã䜿çšããŠãããå®è£ ããæ¹æ³ã¯ããŸãæ確ã§ã¯ãããŸããã
ãµãã¹ã¯ãªãã·ã§ã³ã䜿çšããã«ã¯ãè¿œå ã®ããŒãã«ãå¿ èŠã§ãã
subscription_plans-æéãã©ã³ã®ä¿åçšïŒ
id | service_provider | service_name | äŸ¡æ Œ | äŸ¡æ Œã¿ã€ã | æé |
1 | ãµãŒãã¹ | ãã | 5.00 | ãŠãŒã¶ãŒ | æ |
2 | ãµãŒãã¹ | ãšã³ã¿ãŒãã©ã€ãº | 10.00 | ãŠãŒã¶ãŒ | æ |
3 | ãµãŒãã¹ | ç¡æ | 0.00 | ãŠãŒã¶ãŒ | æ |
ãµãã¹ã¯ãªãã·ã§ã³-ãµãã¹ã¯ãªãã·ã§ã³ãä¿åããã«ã¯ïŒ
id | user_id | plan_id | subscription_id | created_date | æŽæ°æ¥ | æ¯ææ¥ | items_count | ç¶æ |
ãµãã¹ã¯ãªãã·ã§ã³ãã©ãŒã
ãµãã¹ã¯ãªãã·ã§ã³ãã©ãŒã ã¯ã1åéãã®æ¯æããã©ãŒã ã«éåžžã«ãã䌌ãŠããŸãã
<?php $payNowButtonUrl = 'https://www.sandbox.paypal.com/cgi-bin/websc'; $userId = 1 // id $receiverEmail = 'xxx-facilitator@gmail.com'; //email ( paypal ) $serviceId = 1; $serviceName = 'Service Pro'; // ( ) $servicePrice = '5.00'; // - 5$ 1 $quantity = 3; // $amount = $servicePrice * $quantity; // - 15$ $returnUrl = 'http://your-site.com/subscription?status=paymentSuccess'; $customData = ['user_id' => $userId, 'service_id' => $serviceId ]; ?> <form id="createSubscription" action="<?php echo $payNowButtonUrl; ?>" method="post" target="_top"> <input type="hidden" name="cmd" value="_xclick-subscriptions"> <input type="hidden" name="business" value="<?php echo $receiverEmail; ?>"> <input type="hidden" name="lc" value="GB"> <input type="hidden" name="item_name" value="<?php echo $serviceName; ?>"> <input type="hidden" name="no_note" value="1"> <input type="hidden" name="no_shipping" value="1"> <input type="hidden" name="return" value="<?php echo $returnUrl; ?>"> <input type="hidden" name="src" value="1"> <input type="hidden" name="a3" value="<?php echo $amount; ?>"> <input type="hidden" name="p3" value="1"> <input type="hidden" name="t3" value="M"> <input id="customData" type="hidden" name="custom" value="<?php echo json_encode($customData); ?>"> <input type="hidden" name="currency_code" value="USD"> <button type="submit">Subscribe</button> </form>
ãµãã¹ã¯ãªãã·ã§ã³äŸ¡æ Œã¯ããã©ã¡ãŒã¿ãŒa3ã«ãã£ãŠèšå®ãããŸãã ãµãã¹ã¯ãªãã·ã§ã³æéã¯ããã©ã¡ãŒã¿ãŒp3ããã³t3ã䜿çšããŠèšå®ãããŸãïŒãã®äŸã§ã¯ãæ¯æãã¯æ¯æçºçããŸãïŒã
ãããã®ãã©ã¡ãŒã¿ããã³ãã®ä»ã®ãã©ã¡ãŒã¿ã®è©³çŽ°ãªèª¬æã¯ã ããã¥ã¡ã³ãã«èšèŒãããŠããŸã ã
IPN
IPNã®å Žåããã¹ãŠã¯åºæ¬çã«1åéãã®æ¯æããšåãã§ãã 確ãã«ãæã ã¯ããå€ãã®ãªã¯ãšã¹ããåãåãã§ããã ããå€ãã®ã€ãã³ããåŠçããå¿ èŠããããŸãïŒãµãã¹ã¯ãªãã·ã§ã³ã®äœæããµãã¹ã¯ãªãã·ã§ã³ã®æ¯æãããµãã¹ã¯ãªãã·ã§ã³ã®è§£é€ãªã©ã åãšåæ§ã«ãåãªã¯ãšã¹ãã®ä¿¡é Œæ§ã確èªããŠããåŠçããå¿ èŠããããŸãã
ãµãã¹ã¯ãªãã·ã§ã³æ€èšŒ
ããã§ã®ãã¹ãŠã¯ã1åéãã®æ¯æããããå°ãè€éã§ãã æ¯æãã ãã§ãªãããµãã¹ã¯ãªãã·ã§ã³ã®äœæããµãã¹ã¯ãªãã·ã§ã³ã®ãã£ã³ã»ã«ããµãã¹ã¯ãªãã·ã§ã³ã®å€æŽãæ€èšŒããå¿ èŠããããŸãã ã¢ããªã±ãŒã·ã§ã³ã®ããžãã¯ã«å¿ããŠãããããä»ã®äœãã ããšãã°ãProã®æéãã©ã³ã«ã¯æ倧100人ã®ãŠãŒã¶ãŒãå¿ èŠã§ãã ãŸãã¯ãã®ãããªäœãã ç¹°ãè¿ããŸããããã©ãŒã ãäœæãã段éã§ãããããã¹ãŠãèæ ®ã«å ¥ããããšãã§ããŸãã
ãã®å Žåã«æ£ç¢ºã«ç¢ºèªããå¿ èŠããããã®ïŒ
- ãã£ã³ã»ã«ã®å Žåã¯ããµãã¹ã¯ãªãã·ã§ã³ãååšããããšã確èªããŠãã ãã
- ãµãã¹ã¯ãªãã·ã§ã³ã§æ¯æãã«ã¯ãããã確èªããŠãã ãã
- äŸ¡æ Œã¯0ã§ã¯ãããŸãã
- ãµãã¹ã¯ãªãã·ã§ã³ã®ãµã€ãºã«çããæ¯æãé¡
- åä¿¡è ãæ£ããæå®ãããŠãã
- å®äºãããµãã¹ã¯ãªãã·ã§ã³ã¹ããŒã¿ã¹
- ç±³ãã«é貚
- æãæ»ãã®å Žåãæ¯æããååšããæãæ»ãéé¡ãæ¯æãéé¡ãè¶ ããŠããªãããšã確èªããå¿ èŠããããŸãïŒéšåæãæ»ããè¡ã£ãŠããå Žåãæãæ»ãéé¡ã¯æ¯æãããå°ãªãå ŽåããããŸãïŒ
- ãµãã¹ã¯ãªãã·ã§ã³ãäœæããå Žåãæéãã©ã³ãååšããäŸ¡æ ŒãäžèŽããããšã確èªããå¿ èŠããããŸã
<?php function validateSubscription($subscriptionPlan,$myPost){ $userId = $myPost['customData']['user_id']; $userService = new UserService(); $userInfo = $userService->getUserData($userId); $customData = $this->getCustomData($myPost); // if($myPost['txn_type'] == 'subscr_cancel'){ $subscriptionService = new SubscriptionService(); $subscription = $subscriptionService->loadBySubscriptionId($myPost['subscr_id']); if(!$subscription->id){ // return false; } } // elseif($myPost['txn_type'] == 'subscr_payment'){ // if($subscriptionPlan->price * $myPost['customData']['items_count'] != $myPost['mc_gross']){ return false; } // , 0 if($myPost['mc_gross'] == 0){ return false; } // if($myPost['receiver_email'] != 'xxx-facilitator@yandex.ru'){ return false; } // if($myPost['mc_currency'] != 'USD'){ return false; } // if($myPost['payment_status'] != 'Completed'){ return false; } } // elseif($myPost['reason_code'] == 'refund' && $myPost['payment_status'] == 'Refunded'){ $transactionService = new TransactionService(); $lastTransaction = $transactionService->getLastActiveTransactionBySubscription($myPost['subscr_id']); //, if(!$lastTransaction){ return false; } //, if(abs($myPost['mc_gross']) > $lastTransaction['mc_gross']){ return false; } } return true; } ?>
æ¯æãåŠç
æ€èšŒã«æåãããšãæ¯æãã®åŠçãç¶è¡ã§ããŸãã ããã«ã¯ãããã€ãã®å¯èœãªãµãã¹ã¯ãªãã·ã§ã³ç¶æ ããããŸãã
- ãµãã¹ã¯ãªãã·ã§ã³ã¯ååšããŸãã
- æå¹ãªãµãã¹ã¯ãªãã·ã§ã³
- æªç»é²
ãµãã¹ã¯ãªãã·ã§ã³ã®ã¹ããŒã¿ã¹ã«å¿ããŠããªã¯ãšã¹ãã¯ç°ãªãæ¹æ³ã§åŠçãããŸãã
<?php function processPayment($myPost){ $customData = $this->getCustomData($myPost); $userId = $customData['user_id']; $userService = new UserService(); $userInfo = $userService->getUserData($userId); $subscriptionPlanService = new SubscriptionPlanService(); $subscriptionPlan = $subscriptionPlanService->getSubscriptionPlan($myPost); $transactionService = new TransactionService(); $subscriptionService = new SubscriptionService(); if(validateSubscription($subscriptionPlan,$myPost)){ $subscription = $subscriptionService->loadBySubscriptionId($myPost['subscr_id']); $transaction = $transactionService->getTransactionById($myPost['txn_id']); // if($subscription->id){ // if($myPost['txn_type'] == 'subscr_payment'){ // if(!$transaction){ // $subscription->status = 'active'; $subscription->payment_date = $myPost['payment_date']; $subscription->updated_date = date('Ymd H:i:s'); $subscription->save(); // $myPost['relation_id'] = $subscription->id; $myPost['relation_type'] = 'transaction'; $transactionService->createTransaction($myPost); } else{ // . } } // if($myPost['txn_type'] == 'subscr_cancel'){ $subscription->status = 'cancelled'; $subscription->updated_date = date('Ymd H:i:s'); $subscription->save(); } // if($myPost['txn_type'] == 'subscr_eot'){ $subscription->status = 'expired'; $subscription->updated_date = date('Ymd H:i:s'); $subscription->save(); } // if($myPost['txn_type'] == 'subscr_signup'){ } // . . if($myPost['txn_type'] == 'subscr_modify'){ $subscription->status = 'modified'; $subscription->updated_date = date('Ymd H:i:s'); $subscription->save(); } // if($myPost['payment_status'] == 'Refunded' && $myPost['reason_code'] == 'refund'){ // $transactionService->updateTransactionStatus($myPost['parent_txn_id'],'Refunded'); // () $myPost['txn_type'] = 'refund'; $myPost['relation_id'] = $subscription->id; $myPost['relation_type'] = 'subscription'; $transactionService->createTransaction($myPost); } } // else{ // if($myPost['txn_type'] == 'subscr_payment'){ $activeSubscriptions = $subscriptionService->getActiveSubscriptions($userId); // , . if(count($activeSubscriptions) > 0){ // , } elseif(!$transaction){ // $subscription = new Subscription(); $subscription->user_id = $userId; $subscription->plan_id = $subscriptionPlan->id; $subscription->subscription_id = $myPost['subscr_id']; $subscription->created_date = date("Ymd H:i:s"); $subscription->updated_date = date('Ymd H:i:s'); $subscription->payment_date = $myPost['payment_date']; $subscription->items_count = $customData['items_count']; $subscription->status = 'active'; $subscriptionId = $subscription->save(); // $myPost['relation_id'] = $subscriptionId; $myPost['relation_type'] = PaypalTransaction::TRANSACTION_RELATION_SUBSCRIPTION; $transactionService = new PaypalTransaction(); $transactionService->createTransaction($myPost); } else{ // } } // . , if($myPost['txn_type'] == 'subscr_signup'){ } // . .. if($myPost['txn_type'] == 'subscr_modify'){ } } } else{ // } } ?>
ç»é²è§£é€
ãŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ã®äœ¿çšã«ããããããŠããå Žåã«åããŠããµãã¹ã¯ãªãã·ã§ã³ã®ãã£ã³ã»ã«ãå®çŸããŸãã ãã®å ŽåãPaypal Classic Apiã䜿çšããŠãµãã¹ã¯ãªãã·ã§ã³ããã£ã³ã»ã«ããŸãã
APIã䜿çšããã«ã¯ããŠãŒã¶ãŒåããã¹ã¯ãŒãã眲åãå¿ èŠã§ãã ãããã¯ãããã¡ã€ã«èšå®ã§èŠã€ããããšãã§ããŸãã
賌èªè§£é€ã¯ManageRecurringPaymentsProfileStatusã¡ãœããã䜿çšããŠè¡ãããŸã
<?php // $profile_id - id ( $myPost['subscr_id']) // $action - 'Cancel' public function changeSubscriptionStatus($profile_id, $action, $apiCredentials){ $api_request = 'USER=' . urlencode( $apiCredentials['username'] ) . '&PWD=' . urlencode( $apiCredentials['password'] ) . '&SIGNATURE=' . urlencode( $apiCredentials['signature'] ) . '&VERSION=76.0' . '&METHOD=ManageRecurringPaymentsProfileStatus' . '&PROFILEID=' . urlencode( $profile_id ) . '&ACTION=' . urlencode( $action ) . '&NOTE=' . urlencode( 'Profile cancelled at store' ); $ch = curl_init(); curl_setopt( $ch, CURLOPT_URL, 'https://api-3t.sandbox.paypal.com/nvp' ); // For live transactions, change to 'https://api-3t.paypal.com/nvp' curl_setopt( $ch, CURLOPT_VERBOSE, 1 ); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt( $ch, CURLOPT_POST, 1 ); // Set the API parameters for this transaction curl_setopt( $ch, CURLOPT_POSTFIELDS, $api_request ); // Request response from PayPal $response = curl_exec( $ch ); // If no response was received from PayPal there is no point parsing the response if( ! $response ){ return false; } curl_close( $ch ); // An associative array is more usable than a parameter string parse_str( $response, $parsed_response ); return $parsed_response; } ?>
ãã®æ¹æ³ã«ã¯ããã€ãã®åé¡ããããŸãã æ¢ã«ãã£ã³ã»ã«ãããŠãããµãã¹ã¯ãªãã·ã§ã³ã¯ãã£ã³ã»ã«ã§ããŸããã ãã ãããµãã¹ã¯ãªãã·ã§ã³ã®ã¹ããŒã¿ã¹ã確èªã§ããŸããã ãããã£ãŠããµãã¹ã¯ãªãã·ã§ã³ãåžžã«ãã£ã³ã»ã«ããå¿ èŠããããŸãïŒéåžžã®ç¶æ³ã§ã¯ããµãã¹ã¯ãªãã·ã§ã³ã2åãã£ã³ã»ã«ããå¿ èŠã¯ãããŸããïŒã ãã®åé¡ã¯ãã®æçš¿ã§èª¬æãããŠããŸãã
æãæ»ãïŒå šé¡/äžéšïŒ
ããããããµãã¹ã¯ãªãã·ã§ã³ã®ãã£ã³ã»ã«ã«å ããŠããŠãŒã¶ãŒã¯æªäœ¿çšæéã®ãéãè¿ããããšèããŠããŸãïŒæ³šïŒ1ãæé賌èªã1é±éåŸã«ãã£ã³ã»ã«-è²»çšã®75ïŒ ãè¿ãå¿ èŠããããŸãïŒã
Paypal Classic Apiã®RefundTransactionã¡ãœããã䜿çšã§ããŸãã
<?php // $transaction_id - $myPost['txn_id'] // $amount - public function refundTransaction($transaction_id,$apiCredentials$amount = null){ $transaction_id = $transaction['txn_id']; $refundType = 'Full'; if($amount){ $amount = round($amount, 2, PHP_ROUND_HALF_DOWN); $amount = str_replace(',','.',$amount); $refundType = 'Partial'; } $api_request = 'USER=' . urlencode( $apiCredentials['username'] ) . '&PWD=' . urlencode( $apiCredentials['password'] ) . '&SIGNATURE=' . urlencode( $apiCredentials['signature'] ) . '&VERSION=119' . '&METHOD=RefundTransaction' . '&TRANSACTIONID=' . urlencode( $transaction_id ) . '&REFUNDTYPE=' . urlencode( $refundType ) . '&CURRENCYCODE=' . urlencode( 'USD' ); if($amount){ $api_request .= '&AMT=' . urlencode( $amount ); } $ch = curl_init(); curl_setopt( $ch, CURLOPT_URL, 'https://api-3t.sandbox.paypal.com/nvp' ); // For live transactions, change to 'https://api-3t.paypal.com/nvp' curl_setopt( $ch, CURLOPT_VERBOSE, 1 ); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt( $ch, CURLOPT_POST, 1 ); // Set the API parameters for this transaction curl_setopt( $ch, CURLOPT_POSTFIELDS, $api_request ); // Request response from PayPal $response = curl_exec( $ch ); // If no response was received from PayPal there is no point parsing the response if( ! $response ){ return false; } curl_close( $ch ); // An associative array is more usable than a parameter string parse_str( $response, $parsed_response ); return $parsed_response; } ?>
åçé¡ãèšç®ããã«ã¯ã次ã®ã³ãŒãã䜿çšã§ããŸãã ã³ãŒãã¯ãæ¯æã®ãµãã¹ã¯ãªãã·ã§ã³ãªã¿ãŒã³ãèšç®ããããã«èšèšãããŠããŸãã
<?php public static function getTransactionRefundAmount($transaction){ $paymentDate = date('Ym-d',strtotime($transaction['payment_date'])); $currentDate = date('Ym-d'); $paymentDate = new DateTime($paymentDate); $currentDate = new DateTime($currentDate); $dDiff = $paymentDate->diff($currentDate); $days = $dDiff->days; $daysInMonth = cal_days_in_month(CAL_GREGORIAN,$currentDate->format('m'),$currentDate->format('Y')); $amount = $transaction['mc_gross'] - $transaction['mc_gross'] * $days / $daysInMonth; $amount = round($amount, 2, PHP_ROUND_HALF_DOWN); $amount = str_replace(',','.',$amount); return $amount; } ?>
ãµãã¹ã¯ãªãã·ã§ã³ãå€æŽãã
次ã«ããµãã¹ã¯ãªãã·ã§ã³ã®æ¡ä»¶ãå€æŽããæ©èœãè¿œå ããŸãã ããã¯ããŠãŒã¶ãŒãæéãã©ã³ãŸãã¯ãŠãŒã¶ãŒæ°ãå€æŽããå Žåã«å¿ èŠã«ãªããŸãã æ®å¿µãªãããPayPalã¯ãµãã¹ã¯ãªãã·ã§ã³ã®å€æŽã«ç¹å®ã®å¶éã課ããŠããŸãã
ããã§ã¯ããã®åé¡ã«ã€ããŠèª¬æããŸãã
ç§ã¯èªåã§ãã®æ å ±ã確èªããããããŸãããåæã«ããŠãŒã¶ãŒãæéãã©ã³ãå€æŽãããå Žåãããããµãã¹ã¯ãªãã·ã§ã³ã®ã³ã¹ãã¯å€§å¹ ã«å€ãããŸãããã®å ŽåããŸãçŸåšã®ãµãã¹ã¯ãªãã·ã§ã³ããã£ã³ã»ã«ããéšåçãªæãæ»ããè¡ãããšãã§ããŸãã次ã«ãä»ã®ãã©ã¡ãŒã¿ãŒã䜿çšããŠæ°ãããµãã¹ã¯ãªãã·ã§ã³ãäœæããŸãã
ããããããã»ã©çŸããã¯ãããŸããããå®ç§ã«æ©èœããŸãããã®çµæãç§ã¯ãã®ãªãã·ã§ã³ã«æ±ºããŸããããã ããååãšããŠãäžèšã®ãªã³ã¯ã«ã¯ããµãã¹ã¯ãªãã·ã§ã³ã®å€æŽãããæ£ç¢ºã«ããæ¹æ³ã«é¢ããæ å ±ãå«ãŸããŠããŸãã
ãããã«
ãã®çµæã1åéãã®æ¯æããšPaypalãµãã¹ã¯ãªãã·ã§ã³ã§äœæ¥ããæ©äŒãåŸãããŸãã1åéãã®ãµãã¹ã¯ãªãã·ã§ã³æ¯æããåŠçããããã®ããžãã¯ã¯ãWebã¢ããªã±ãŒã·ã§ã³ã«ãããŸãã
æéãçµã€ã«ã€ããŠãæ°ããæéãã©ã³ãè¿œå ããå€ãæéãã©ã³ãå€æŽããããšãã§ããŸãïŒãããæ éã«è¡ããæ€èšŒã確èªãããªã©ïŒã
ããã§è©±ã¯çµããã§ãããæž èŽããããšãããããŸããããã®èšäºãã圹ã«ç«ãŠã°å¹žãã§ããã³ã¡ã³ãã§è³ªåã«çããŠããããã§ãã
UPDã¯ïŒããããšããDaniyar94ããIPNã«å ããŠPDTã䜿çšã§ããŸããããã¯ãæ¯æãã®æåã«é¢ããã¡ãã»ãŒãžãããã«è¡šç€ºããã®ã«åœ¹ç«ã¡ãŸãã詳现ã¯ãã¡ãhabrahabr.ru/post/266091/#comment_8560801