大体流程:
1.IOS端需要在iTunes Connect上面添加配置一些内购商品,并审核通过,每个内购商品有自己的唯一标识product_id。
2.PHP后端要有一套与之对应的内购商品、IOS应用唯一标识bundle_id和应用秘钥配置,以便用于验证。如下在tp5的config中做了配置:
//IOS内购配置 'applepay' =>[ 'bundle_id' => 'com.oyhdo.lws', //应用唯一标识 'products' => ['com.lws.good1','com.lws.good2','com.lws.good3'], //内购商品 'apple_secret' => '6666666' //应用密钥,在itunes中获取 ],
3.IOS端调起内购支付,支付成功后会返回票据receipt_data,IOS端需将此票据及其他参数提交给后端接口验证(建议加密)。
(后端接收到的receipt_data票据信息打印如下:)
array(3) { ["receipt"] => array(18) { ["receipt_type"] => string(17) "ProductionSandbox" ["adam_id"] => int(0) ["app_item_id"] => int(0) ["bundle_id"] => string(18) "com.oyhdo.lws" ["application_version"] => string(1) "1" ["download_id"] => int(0) ["version_external_identifier"] => int(0) ["receipt_creation_date"] => string(27) "2019-01-16 13:24:02 Etc/GMT" ["receipt_creation_date_ms"] => string(13) "1547645042000" ["receipt_creation_date_pst"] => string(39) "2019-01-16 05:24:02 America/Los_Angeles" ["request_date"] => string(27) "2019-01-16 13:26:00 Etc/GMT" ["request_date_ms"] => string(13) "1547645160103" ["request_date_pst"] => string(39) "2019-01-16 05:26:00 America/Los_Angeles" ["original_purchase_date"] => string(27) "2013-08-01 07:00:00 Etc/GMT" ["original_purchase_date_ms"] => string(13) "1375340400000" ["original_purchase_date_pst"] => string(39) "2013-08-01 00:00:00 America/Los_Angeles" ["original_application_version"] => string(3) "1.0" ["in_app"] => array(1) { [0] => array(11) { ["quantity"] => string(1) "1" ["product_id"] => string(15) "com.lws.good1" ["transaction_id"] => string(16) "1000000494954657" ["original_transaction_id"] => string(16) "1000000494954657" ["purchase_date"] => string(27) "2019-01-16 13:24:02 Etc/GMT" ["purchase_date_ms"] => string(13) "1547645042000" ["purchase_date_pst"] => string(39) "2019-01-16 05:24:02 America/Los_Angeles" ["original_purchase_date"] => string(27) "2019-01-16 13:24:02 Etc/GMT" ["original_purchase_date_ms"] => string(13) "1547645042000" ["original_purchase_date_pst"] => string(39) "2019-01-16 05:24:02 America/Los_Angeles" ["is_trial_period"] => string(5) "false" } } } ["status"] => int(0) ["environment"] => string(7) "Sandbox" }
4.PHP后端对票据进行验证,并执行一些业务逻辑。代码如下:
//IOS内购 public function applepay(){ $arr = ['code'=>0,'msg'=>'支付失败','data'=>[]]; $user_id = $_POST['user_id'];//用户id $money = $_POST['money']; //支付金额 $receipt_data = $_POST['receipt_data'];//票据 if ($user_id && $money>0 && $receipt_data) { //生成商家订单号 $order_no = 'IOS'.time().rand(10000,99999); /** 添加订单记录 省略逻辑...... **/ if($order_log){ //验证收据 $res = $this->validate_applepay($receipt_data,false); //false沙盒 true正式 if(intval($res['status'])==0) { //验证成功 $bundleId = config('bundle_id'); $products = config('products'); $bundle_id = $res['receipt']['bundle_id']; $product_id = $res['receipt']['in_app'][0]['product_id']; if($bundle_id==$bundleId && in_array($product_id,$products)){ //更新订单记录 $data['trade_no'] = $res['receipt']['in_app'][0]['transaction_id'];//内购交易订单号 $data['total_fee'] = $money; //总金额 $data['pay_time'] = time(); //支付成功时间 $data['state'] = 1;//修改订单状态 $updatelog = PayModel::updateLog($order_no,$data); if($updatelog){ $arr['code'] = 200; $arr['msg'] = '支付成功'; } }else{ $arr['msg'] = '配置错误'; } }else{ //验证失败 $arr['code'] = $res['status']; } } }else{ $arr['msg'] = '参数错误'; } echo json_encode($arr); } /** * IOS内购验证票据 * @param string $receipt_data 付款后凭证 * @return array 验证是否成功 */ private function validate_applepay($receipt_data,$sandbox=false){ $apple_secret = config('applepay.apple_secret'); $jsonData = array('receipt-data'=>$receipt_data,'password'=>$apple_secret); $post_json = json_encode($jsonData); if($sandbox){ $url="https://buy.itunes.apple.com/verifyReceipt";//正式环境 }else{ $url="https://sandbox.itunes.apple.com/verifyReceipt";//沙盒环境 } $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_json); $result = curl_exec($ch); curl_close($ch); return json_decode($result,true); //返回status示例: // * 0 验证成功 // * 21000 App Store不能读取你提供的JSON对象 // * 21002 receipt-data域的数据有问题 // * 21003 receipt无法通过验证 // * 21004 提供的shared secret不匹配你账号中的shared secret // * 21005 receipt服务器当前不可用 // * 21006 receipt合法,但是订阅已过期。服务器接收到这个状态码时,receipt数据仍然会解码并一起发送 // * 21007 receipt是Sandbox receipt,但却发送至生产系统的验证服务 // * 21008 receipt是生产receipt,但却发送至Sandbox环境的验证服务 }
https://blog.csdn.net/msllws/article/details/86515824
最新评论: