paypal php 实现详细攻略
一、准备工作
登录 https://www.paypal.com/ 注册一个主账号(选择个人账号、企业账后都可)
申请完成后登录https://developer.paypal.com/ 在后台右侧菜地点击“Accounts”,可以看到系统自动给分配的两个沙箱环境的账号。类型为Personal是个人账号、类型为Business是商家账号。点进去可以看到密码
开启PDT设置同步回调地址(这步拿到at_token return回调使用)
用系统分配的卖家账号登录沙箱地址https://www.sandbox.paypal.com/
二: 调用接口,获取token,创建订单,生成支付链接,然后捕获订单确认付款,处理回调事件。
Developer Dashboard 切换测试模式和正式模式的链接
三:修改回调事件在选择的应用,点击进去后可以修改增加,捕获订单接口在回调的时候调用
参考链接: 【支付】PayPal支付通道 Java对接 (下单 付款 确认 退款 查询 回调)_java对接paypal-CSDN博客
php PayPal 支付/回调 - 加菲猫and大白 - 博客园
/** * 统一下单接口 * @param $order * @param string $trade_type * @return array */ function create_order_bak() { $domain = $this->request->domain(); $order['order_no'] = 10191; $arr = [ 'purchase_units' => [ [ 'custom_id' => 1, 'reference_id' => $order['order_no'],//订单ID 'amount' => [ 'currency_code' => 'USD', 'value' => 1 ] ] ], 'intent' => 'CAPTURE', 'payment_source' => [ 'paypal' => [ 'experience_context' => [ 'payment_method_preference' => 'IMMEDIATE_PAYMENT_REQUIRED', 'payment_method_selected' => 'PAYPAL', 'brand_name' => 'TEST', 'landing_page' => 'GUEST_CHECKOUT',//直接付款 'user_action' => 'PAY_NOW', 'return_url' => 'https://1688order.com',//付款后回调地址 'cancel_url' => 'https://1688order.com'//取消付款后回调地址 ] ] ] ]; $result = $this->post( self::ONLINE_USEEPAY_SANDBOX_ENDPOINT.'/v2/checkout/orders', ['Content-Type: application/json','Authorization: Bearer '.$this->getPaypalToken(),'PayPal-Request-Id: '.'TEST-'.$order['order_no']], json_encode($arr) ); // Log::write('创建订单返回信息:'.var_export($result, true)); if(isset($result['id'])){ return array('code' => 1, 'msg' => '创建订单成功', 'data' => $result); }else{ // return array('code' => 0, 'data' => $result['message']); } } /** * id 是下单的时候生成的订单的ID * paypal 回调后 捕获订单付款 */ function paypalOrderCapture($id){ $result = $this->post( self::ONLINE_USEEPAY_SANDBOX_ENDPOINT.'/v2/checkout/orders/'.$id.'/capture', ['Content-Type: application/json','Authorization: Bearer '.$this->getPaypalToken(),'PayPal-Request-Id: '.'TEST-'.$id] ); return $result['status'] == 'COMPLETED' ? $result : false; }
/** * 获取token,一般返回来的access token有效时是9个小时 **/ function getPaypalToken(){ $paypal_token_config = cache("paypal-token-new"); $end_time = time(); if($paypal_token_config) { $result = $paypal_token_config; $results = json_decode($result, true); $end_time = $results['time'] + $results['expires_in']; } if($end_time - time() < 1800){ //更新access token $result = $this->post( self::ONLINE_USEEPAY_SANDBOX_ENDPOINT.'/v1/oauth2/token', [ 'Content-Type: application/x-www-form-urlencoded', 'Authorization:Basic '.base64_encode(self::ONLINE_CLEINTID.":".self::ONLINE_CLIENTSECRET) ], http_build_query(['grant_type' => 'client_credentials']) ); if(isset($result['app_id'])){ $result['time'] = time(); cache("paypal-token-new",json_encode($result),3600); } } return isset($results['access_token']) ? $results['access_token'] : false; }
/** * 发起POST请求 */ public function post($url, $headers, $request = array()) { $header_res = []; $curl = curl_init($url); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $request); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_HEADERFUNCTION, function ($curl, $header) use (&$header_res) { $len = strlen($header); $header = explode(':', $header, 2); if (count($header) < 2) // ignore invalid headers return $len; $header_res[strtolower(trim($header[0]))][] = trim($header[1]); return $len; } ); $response_data = curl_exec($curl); curl_close($curl); $result = json_decode($response_data, true); return $result; }
//回调地址 public function notify_order(){ Log::write('paypal 支付进来了'); $payload = @file_get_contents('php://input'); // 调用 record() 方法记录日志 // Log::write('content'.var_export($payload, true)); $ret = json_decode($payload, true); Log::write('数组格式返回:'.var_export($ret, true)); // Log::write('id'.var_export($ret['resource']['id'], true)); // Log::write('status'.var_export($ret['resource']['status'], true)); $order_id = $ret['resource']['id']; $result = $this->paypalOrderCapture($order_id); Log::write('确认付款后返回结果:'.var_export($result, true)); $captureId = $result['purchase_units'][0]['payments']['captures'][0]['id'];//捕获ID,在退款的时候使用 Log::write('确认支付后的支付状态是:'.var_export($result['status'], true)); Log::write('捕获ID是:'.var_export($captureId, true)); $web_order_id = $result['purchase_units'][0]['reference_id'];//网站下单的订单ID Log::write('网站下单的订单ID:'.var_export($web_order_id, true)); $buy_type = $result['purchase_units'][0]['payments']['captures'][0]['custom_id'];//下单类型 Log::write('网站下单类型:'.var_export($buy_type, true)); //如果确认支付成功 if ($result['status'] == 'COMPLETED'){ //调用修改订单状态后续逻辑 $res = PayNotifyLogic::handle('order_buy', $web_order_id, ['buy_type'=>$buy_type,'payment_intent_id'=>$captureId]); if ($res) { $this->success('success', url('/pc/user/order/detail', ['id' => $order_id])); } }else{ Log::write('确认付款失败返回结果:'.var_export($result, true)); } }