Showing
3 changed files
with
94 additions
and
9 deletions
| ... | @@ -73,6 +73,8 @@ class OrderController extends Controller | ... | @@ -73,6 +73,8 @@ class OrderController extends Controller |
| 73 | return DB::transaction(function ()use ($user_id, $member_id, $source, $number){ | 73 | return DB::transaction(function ()use ($user_id, $member_id, $source, $number){ |
| 74 | // 获取商品信息 | 74 | // 获取商品信息 |
| 75 | $membership_good = MembershipGood::query()->where('id',$member_id)->first(); | 75 | $membership_good = MembershipGood::query()->where('id',$member_id)->first(); |
| 76 | + if (!$membership_good) throw new \Exception('没有此商品'); | ||
| 77 | + | ||
| 76 | $membership = $membership_good->membership()->first(); | 78 | $membership = $membership_good->membership()->first(); |
| 77 | 79 | ||
| 78 | // 实付金额 = 商品金额 | 80 | // 实付金额 = 商品金额 | ... | ... |
| ... | @@ -37,18 +37,25 @@ class PayController extends Controller | ... | @@ -37,18 +37,25 @@ class PayController extends Controller |
| 37 | */ | 37 | */ |
| 38 | public function store(Request $request) | 38 | public function store(Request $request) |
| 39 | { | 39 | { |
| 40 | - // | 40 | + // 回调 |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | /** | 43 | /** |
| 44 | * Display the specified resource. | 44 | * Display the specified resource. |
| 45 | * | 45 | * |
| 46 | * @param int $id | 46 | * @param int $id |
| 47 | - * @return \Illuminate\Http\Response | 47 | + * @param Request $request |
| 48 | + * @param PaymentFactory $factory | ||
| 49 | + * @return \Illuminate\Http\JsonResponse | ||
| 50 | + * @throws \Exception | ||
| 48 | */ | 51 | */ |
| 49 | - public function show($id) | 52 | + public function show($id, Request $request, PaymentFactory $factory) |
| 50 | { | 53 | { |
| 51 | - // | 54 | + $pay_type = $request->get('pay_type'); |
| 55 | + | ||
| 56 | + $capture = $factory->init($pay_type)->capture($id); | ||
| 57 | + | ||
| 58 | + return Response::success($capture); | ||
| 52 | } | 59 | } |
| 53 | 60 | ||
| 54 | /** | 61 | /** | ... | ... |
| ... | @@ -17,11 +17,10 @@ class PaypalPayment implements PaymentInterface | ... | @@ -17,11 +17,10 @@ class PaypalPayment implements PaymentInterface |
| 17 | 17 | ||
| 18 | const IS_SANDBOX = true; | 18 | const IS_SANDBOX = true; |
| 19 | 19 | ||
| 20 | - public $authUrl = 'https://api-m.sandbox.paypal.com/v1/oauth2/token'; | 20 | + public $baseUrl = 'https://api-m.paypal.com'; |
| 21 | 21 | ||
| 22 | - public $paySandboxUrl = 'https://api-m.sandbox.paypal.com'; | 22 | + public $baseUrlSandbox = 'https://api-m.sandbox.paypal.com'; |
| 23 | 23 | ||
| 24 | - public $payUrl = 'https://api-m.paypal.com'; | ||
| 25 | 24 | ||
| 26 | public $clientId = 'AdDRE91WSp5q1fYLODpJduc2mRjA_v6E205SvkfVSOgvr98xLeyDCHY4OPAaSFMK1SHYOfJ4TksHSX1-'; | 25 | public $clientId = 'AdDRE91WSp5q1fYLODpJduc2mRjA_v6E205SvkfVSOgvr98xLeyDCHY4OPAaSFMK1SHYOfJ4TksHSX1-'; |
| 27 | public $secret = 'EDoy_PVrFyobWt9DzAMRMikJwWCXenkWSx9CGFz0MxHt3a8fs6v-LnORMilIbftb2GwBKxOoTVZNBHNR'; | 26 | public $secret = 'EDoy_PVrFyobWt9DzAMRMikJwWCXenkWSx9CGFz0MxHt3a8fs6v-LnORMilIbftb2GwBKxOoTVZNBHNR'; |
| ... | @@ -38,13 +37,14 @@ class PaypalPayment implements PaymentInterface | ... | @@ -38,13 +37,14 @@ class PaypalPayment implements PaymentInterface |
| 38 | $this->accessToken = $access_token; | 37 | $this->accessToken = $access_token; |
| 39 | }else{ | 38 | }else{ |
| 40 | $client = new Client([ | 39 | $client = new Client([ |
| 40 | + 'base_uri' => $this->baseUrlSandbox, | ||
| 41 | 'headers'=>[ | 41 | 'headers'=>[ |
| 42 | 'Content-Type' => 'application/x-www-form-urlencoded', | 42 | 'Content-Type' => 'application/x-www-form-urlencoded', |
| 43 | 'Accept'=>'application/json', | 43 | 'Accept'=>'application/json', |
| 44 | ] | 44 | ] |
| 45 | ]); | 45 | ]); |
| 46 | 46 | ||
| 47 | - $response = $client->post($this->authUrl,[ | 47 | + $response = $client->post('/v1/oauth2/token',[ |
| 48 | 'form_params'=>['grant_type' => 'client_credentials'], | 48 | 'form_params'=>['grant_type' => 'client_credentials'], |
| 49 | 'auth' => [$this->clientId, $this->secret], | 49 | 'auth' => [$this->clientId, $this->secret], |
| 50 | ]); | 50 | ]); |
| ... | @@ -56,11 +56,87 @@ class PaypalPayment implements PaymentInterface | ... | @@ -56,11 +56,87 @@ class PaypalPayment implements PaymentInterface |
| 56 | } | 56 | } |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | + /** | ||
| 60 | + * Setting up the JSON request body for creating the Order. The Intent in the | ||
| 61 | + * request body should be set as "CAPTURE" for capture intent flow. | ||
| 62 | + * @param Order $order | ||
| 63 | + * @return array | ||
| 64 | + */ | ||
| 65 | + private static function buildCreateOrderRequestBody(Order $order) | ||
| 66 | + { | ||
| 67 | + return array( | ||
| 68 | + 'intent' => 'CAPTURE', //CAPTURE 商家打算在客户付款后立即扣款。 AUTHORIZE 商家打算在客户付款后授权付款并暂停资金 | ||
| 69 | + 'application_context' => | ||
| 70 | + array( | ||
| 71 | + 'return_url' => 'https://example.com/return', // todo | ||
| 72 | + 'cancel_url' => 'https://example.com/cancel', // todo 这里要询问reason app是否有schema, | ||
| 73 | + 'brand_name' => 'Parlando', //覆盖 PayPal 网站上 PayPal 帐户中公司名称的标签。 | ||
| 74 | + 'locale' => 'en-US', //zh-CN | ||
| 75 | + 'landing_page' => 'NO_PREFERENCE', //LOGIN / BILLING / NO_PREFERENCE | ||
| 76 | + 'shipping_preference' => 'NO_SHIPPING', //运输偏好 | ||
| 77 | + 'user_action' => 'PAY_NOW', | ||
| 78 | + ), | ||
| 79 | + 'purchase_units' => | ||
| 80 | + array( | ||
| 81 | + 0 => | ||
| 82 | + array( | ||
| 83 | + 'description' => 'Parlando 3 Month Vip', // 购买说明 | ||
| 84 | + 'custom_id' => 'osnxxxxxx123', //API 调用者提供的外部 ID 可以理解为order_id osnxxxxxx | ||
| 85 | + 'soft_descriptor' => 'PayPal Parlando Vip', // 出现在付款人卡对帐单上的对帐单描述符的动态文本 最大长度:22. | ||
| 86 | + 'amount' => | ||
| 87 | + array( | ||
| 88 | + 'currency_code' => 'USD', // CNY | ||
| 89 | + 'value' => '220.00', // | ||
| 90 | + ), | ||
| 91 | + ), | ||
| 92 | + ), | ||
| 93 | + ); | ||
| 94 | + } | ||
| 95 | + | ||
| 59 | public function prepare(Order $order) | 96 | public function prepare(Order $order) |
| 60 | { | 97 | { |
| 61 | // 在PayPal上创建一个订单,它会返回一个订单对象,它有一个订单id | 98 | // 在PayPal上创建一个订单,它会返回一个订单对象,它有一个订单id |
| 99 | + $client = new Client([ | ||
| 100 | + 'base_uri' => $this->baseUrlSandbox, | ||
| 101 | + 'headers'=>[ | ||
| 102 | + 'Content-Type' => 'application/json', | ||
| 103 | + 'Authorization' => 'Bearer ' . $this->accessToken, | ||
| 104 | + 'Prefer' => 'return=representation', | ||
| 105 | + ] | ||
| 106 | + ]); | ||
| 107 | + | ||
| 108 | + $response = $client->post('/v2/checkout/orders',[ | ||
| 109 | + 'json' => self::buildCreateOrderRequestBody($order), | ||
| 110 | + ]); | ||
| 111 | + $body = $response->getBody(); | ||
| 112 | + $content = json_decode($body->getContents(),true); | ||
| 113 | + | ||
| 114 | + return $content; | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + public function capture($orderId) | ||
| 118 | + { | ||
| 119 | + $client = new Client([ | ||
| 120 | + 'base_uri' => $this->baseUrlSandbox, | ||
| 121 | + 'headers'=>[ | ||
| 122 | + 'Content-Type' => 'application/json', | ||
| 123 | + 'Authorization' => 'Bearer ' . $this->accessToken, | ||
| 124 | + 'Prefer' => 'return=representation', | ||
| 125 | + ] | ||
| 126 | + ]); | ||
| 127 | + | ||
| 128 | + $response = $client->post('/v2/checkout/orders/' . $orderId . '/capture'); | ||
| 129 | + $body = $response->getBody(); | ||
| 130 | + $content = json_decode($body->getContents(),true); | ||
| 131 | + | ||
| 132 | + | ||
| 133 | + // todo 应该使用队列,异步执行回调程序 | ||
| 62 | 134 | ||
| 135 | + return $content; | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + public function notify() | ||
| 139 | + { | ||
| 63 | 140 | ||
| 64 | - return $this->accessToken; | ||
| 65 | } | 141 | } |
| 66 | } | 142 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment