123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- <?php
- defined('IN_WEB') or die('Include Error!');
- /**
- * 苹果支付
- app store返回码说明:
- 状态码 描述
- 21000 App Store无法读取你提供的JSON数据
- 21002 收据数据不符合格式
- 21003 收据无法被验证
- 21004 你提供的共享密钥和账户的共享密钥不一致
- 21005 收据服务器当前不可用
- 21006 收据是有效的,但订阅服务已经过期。当收到这个信息时,解码后的收据信息也包含在返回内容中
- 21007 收据信息是测试用(sandbox),但却被发送到产品环境中验证
- 21008 收据信息是产品环境中使用,但却被发送到测试环境中验证
- 注意:在这里的非零状态码只是针对自动更新型订阅服务,不能将这些状态码用在测试其他类型产品的返回值中。
- */
- class ModelPaymentapple
- {
- private $_urlBuy = "https://buy.itunes.apple.com/verifyReceipt";
- private $_urlSanbox = "https://sandbox.itunes.apple.com/verifyReceipt";
- private $isSandbox = 0;
- private $_tkey = '';//苹果支付id
- private $_orderId = '';//苹果订单ID, 当客户端传过来为空时候使用
- /**
- * 验证苹果支付
- * @param $param
- * @param string $identifyKey
- * @return bool
- * Created by: Owen
- * Created on: 2020/12/5 10:54
- * PS:
- * 21000 App Store不能读取你提供的JSON对象
- 21002 receipt-data域的数据有问题 =》 receipt 错误
- 21003 receipt无法通过验证 =》 需要传输密码
- 21004 提供的shared secret不匹配你账号中的shared secret =》 需要传输密码
- 21005 receipt服务器当前不可用
- 21006 receipt合法,但是订阅已过期。服务器接收到这个状态码时,receipt数据仍然会解码并一起发送
- 21007 receipt是Sandbox receipt,但却发送至生产系统的验证服务 =》 沙盒凭证
- 21008 receipt是生产receipt,但却发送至Sandbox环境的验证服务
- */
- public function validateApplePay($param,$identifyKey = 'transaction_id', $passVersion = 0){
- $receipt = $param['receipt'];
- $password = "b20b5d00f0d143f39c9f598503fa4dc9";
- $transactionId = oo::functions()->escape($param['transactionId']);
- $url = $this->isSandbox ? $this->_urlSanbox : $this->_urlBuy;
- $postData = json_encode(["receipt-data" => $receipt]);
- $postDataPassWord = json_encode(["receipt-data" => $receipt,"password" => $password]);
- $ret = oo::functions()->curl($url, $postData);
- if($ret['status'] == 21004 || $ret['status'] == 21003){
- $ret = oo::functions()->curl($url,$postDataPassWord);
- }
- //TODO苹果临时过审包处理
- $bundleIds = ['com.astak.crazyspin', 'com.gworld.crazyspinios'];
- if($ret['status'] === 0 && in_array($ret['receipt']['bundle_id'], $bundleIds)){
- $in_app_data = $ret['receipt']['in_app'];
- if($identifyKey == "original_transaction_id"){
- array_multisort(array_column($in_app_data,'expires_date_ms'),SORT_DESC,$in_app_data);
- }
- foreach ($in_app_data as $row){
- if($row[$identifyKey] == $transactionId){
- return $row;
- }
- }
- oo::logs()->debug3(array("error"=>"transactionId error",'param'=>$param,'appleOrderInfo'=>$ret, "identifyKey" => $identifyKey), 'validateApplePay.log');
- return false;
- }else if($ret['status'] == 21007){//沙盒测试
- $retSandbox = oo::functions()->curl($this->_urlSanbox,$postData);
- if($retSandbox['status'] == 21004 || $retSandbox['status'] == 21003){
- $retSandbox = oo::functions()->curl($this->_urlSanbox,$postDataPassWord);
- }
- if($retSandbox['status'] === 0 && in_array($retSandbox['receipt']['bundle_id'], $bundleIds)){
- $in_app_data = $retSandbox['receipt']['in_app'];
- if($identifyKey == "original_transaction_id"){
- $in_app_data = array_reverse($in_app_data);
- }
- foreach ($in_app_data as $row){
- if($row[$identifyKey] == $transactionId){
- return $row;
- }
- }
- oo::logs()->debug3(array("error"=>"transactionId error",'param'=>$param,'appleOrderInfo'=>$retSandbox, "identifyKey" => $identifyKey), 'validateApplePay2.log');
- return false;
- }else{
- oo::logs()->debug3(array("error"=>"package name error",'param'=>$param,'appleOrderInfo'=>$retSandbox, "identifyKey" => $identifyKey), 'validateApplePay2.log');
- return false;
- }
- }else{
- oo::logs()->debug3(array("error"=>"status error","ret" => $ret, "receipt" => $receipt, "param" => $param, "identifyKey" => $identifyKey), 'validateApplePay2.log');
- return false;
- }
- }
- public function crazyGodDeliveryApplePay($param){
- $ret = $this->validateApplePay($param);//验证失败
- if( !$ret ){
- return false;
- }
- //本地的商品和appleID验证
- $orderInfo = $this->verificationCrazyGod($param['uid'],$param['orderId'],$ret);
- if (!$orderInfo) {
- return false;
- }
- return array_merge($ret,$orderInfo);
- }
- public function verificationCrazyGod($uid,$orderId,$param){
- $tb = otable::summarylist();
- $transaction_id = $param['transaction_id'];
- $sql = "SELECT * FROM {$tb} WHERE sl_platform_serial_num='{$transaction_id}' AND sl_status > 1";
- $transaction = oo::commonOprDb('common')->getOne($sql,1);
- if(!empty($transaction)){
- oo::logs()->debug3(array('uid' => $uid, 'msg' => 'transaction_id is be used'),'verification_apple.log');
- return ['order_id'=>$transaction['order_id'],'gid'=>$transaction['gid'], 'transaction_id'=>$transaction_id ,'status'=>2];
- }
- $tb = otable::payment($uid);
- $orderInfo = oo::commonOprDb('payment')->getOne("SELECT * FROM {$tb} WHERE order_id='{$orderId}' LIMIT 1",1);
- if(empty($orderInfo)){
- oo::logs()->debug3(array('uid' => $uid, 'msg' => 'order empty'),'verification_apple_error.log');
- return false;
- }
- $gid = intval($orderInfo['gid']);
- $status = intval($orderInfo['status']);
- return ['order_id'=>$orderId,'gid'=>$gid, 'transaction_id'=>$transaction_id ,'status'=>$status];
- }
- //验证参数 transaction-id是否用过
- public function verification($param)
- {
- $uid = oo::functions()->uint($param['uid']);
- $orderId = oo::functions()->escape($param['orderId']);
- $receipt = oo::functions()->escape($param['receipt']);
- $receipt = base64_decode($receipt);
- $p = '#.*purchase\-info" =(.*?);#iU';
- $str = preg_match_all($p, $receipt, $m);
- if ($str == 0) {//无法匹配
- oo::logs()->debug3(array('ret' => 1, 'uid' => $uid),'verification_apple.log');
- return false;
- }
- $keyInfo = trim($m[1][0], " \" ");//需要的关键数据
- $keyInfo = base64_decode($keyInfo);
- $p2 = '#.*"(.*?)" = "(.*?)";#iU';
- $str2 = preg_match_all($p2, $keyInfo, $m2);
- if ($str2 == 0) {//无法匹配
- oo::logs()->debug3(array('ret' => 2, 'uid' => $uid),'verification_apple.log');
- return false;
- }
- $paramName = array_flip($m2[1]);
- //获取2个关键参数 transaction-id 和 product-id
- $transaction_idKey = $paramName['transaction-id'];
- $product_idKey = $paramName['product-id'];
- $transaction_idVal = $m2[2][$transaction_idKey];//苹果业务ID
- $product_idVal = $m2[2][$product_idKey];//商品ID
- if ($orderId) {
- //验证商品对不对
- $dbGoods = oo::commonOprModel('goods')->getGpidByOrderIdCrazyGod($orderId);
- if (!$dbGoods) {
- oo::logs()->debug3(array('ret' => 3, 'uid' => $uid, 'orderId' => $orderId, 'dbGoods' => $dbGoods),'verification_apple.log');
- return false;
- }
- if ($dbGoods != $product_idVal) {//商品名称错误
- oo::logs()->debug3(array('ret' => 4, 'uid' => $uid, 'orderId' => $orderId, 'dbGoods' => $dbGoods, 'product_idVal' => $product_idVal, 'm2' => $m2, 'paramName' => $paramName),'verification_apple.log');
- return false;
- }
- }else{
- //此次判断没有订单ID时
- // $orderId = oo::commonOprModel('goods')->getOrderByUidAndgpid($uid, $product_idVal);
- $orderId = oo::commonOprModel('goods')->getOrderByUidAndgpidCrazyGod($uid, $product_idVal);
- if (!$orderId) {
- oo::logs()->debug3(array('ret' => 6, 'uid' => $uid, 'product_idVal' => $product_idVal),'verification_apple.log');
- return false;
- }
- $this->_orderId = $orderId;
- }
- $tkey = 'APPLEPAYT:'.$transaction_idVal;
- $tVal = oo::commonOprRedis('common')->get($tkey);
- if ($tVal) {
- oo::logs()->debug3(array('ret' => 5, 'uid' => $uid, 'transaction_idVal' => $transaction_idVal, 'm2' => $m2),'verification_apple.log');
- return false;
- }
- $this->_tkey = $transaction_idVal;
- return true;
- }
- /**
- * 苹果下单接口
- */
- public function deliveryApplePay($param){
- $data = array('code' => 2);
- //本地的商品和appleID验证
- $retVerification = $this->verification($param);
- if (!$retVerification) {
- return $data;
- }
- $ret = $this->validateApplePay($param);//验证失败
- if( !$ret ){
- return $data;
- }
- $uid = oo::functions()->uint($param['uid']);
- $orderId = oo::functions()->escape($param['orderId']);
- $orderId = empty($orderId) ? $this->_orderId : $orderId;
- $pubDeliveryRet = oo::commonOprModel('payment')->pubDelivery($uid, $orderId, $this->_tkey);
- if( $pubDeliveryRet != true ){
- oo::logs()->debug3(array('pubDeliveryRet' => $pubDeliveryRet, 'uid' => $uid, 'orderid' => $orderId), 'verification_apple.log');
- return $data;
- }
- //验证通过记录apple支付ID
- oo::commonOprRedis('common')->setex('APPLEPAYT:'.$this->_tkey, 1);
- $data['code'] = 1;
- return $data;
- }
- }
|