PHP:计算小数点后位数

本文提供两种方法,一种将小数变成字符串,然后用”.“来截取,去.后的子字符串长度。还有一种是讲小数*10的N次方,比如10的8次方再对8次方取余数,再不断对10求余,直到对10求余的结果不为0。

相比来说,第一种方法要好不少,理由是这样的,比如1.000004在很边界的时候或者0.99999这样子PHP处理会有问题,会有误差,导致得到的位数不一样。而且精度难以把握,所以处理这种跟边界有关的问题最后能用字符串还是字符串来做。

第一种

private function _getFloatLength($num) {
$count = 0;
 
$temp = explode ( '.', $num );
 
if (sizeof ( $temp ) > 1) {
$decimal = end ( $temp );
$count = strlen ( $decimal );
}
 
return $count;
}

第二种

function getfloatlength($a){
	if(($a-(int)$a)<1E-9){
		$count=0;
	}
	$a=fmod(1E9*$a,1E9);
	while($a%10==0){
		if($a==0)break;
		$a=$a/10;
		$count--;
	}
	return count;
}

php生成随机红包

/**
     *   
     * @param $packet_total 红包总额 
     * @param $packet_count 红包个数 
     * @param $packet_max 每个小红包的最大额 
     * @param $packet_min 每个小红包的最小额 
     * @return 存放生成的每个小红包的值的一维数组 
     */
    public function getpacket() {

        $father_toal = $packet_total = input(‘packet_total’);
        $packet_count = input(‘packet_count’);
        $middle = $packet_count/2;   //用于判断用那种方法发红包
        //当已经分配了半数后最小值用$packet_min
        $packet_min = ($packet_total/$packet_count)*0.1;
        //当已经分配了小于半数时最小值用$packet_min1
        $packet_min1 = ($packet_total/$packet_count)*0.5;
        if($packet_min<0.01 && $packet_min1<0.01){
            return json_encode(array(‘status’=>0,’msg’=>”金额太少,红包数太多,小气鬼!”));
        }
        $n = $packet_count;
        for ($i = 0; $i < $packet_count – 1; $i++) {
            if($i <= $middle){
                $safe_total1 = (($packet_total – ($packet_count – $i) * $packet_min1) / ($packet_count – $i))*5; //随机安全上限  
                $money = mt_rand($packet_min1 * 100, $safe_total1 * 100) / 100;
                if($money<=0){
                    echo “hello”;break;
                }
                $result[] = round($money,2);
                $packet_total = $packet_total – $money;
            }else{
                $safe_total = ($packet_total – ($packet_count – $i) * $packet_min) / ($packet_count – $i); //随机安全上限  
                $money = mt_rand($packet_min * 100, $safe_total * 100) / 100;
                if($money<=0){
                    $money = 0.01;
                }
                $result[] = $money;
                $packet_total = $packet_total – $money;
            }
            
        }
        
        $left_money = $father_toal – array_sum($result);
        $result[] = $left_money;
         
        return json_encode($result);

    }

php使用正则替换过滤掉js(script)脚本例子

jquery中文网为您提供php使用正则替换过滤掉js(script)脚本例子等资源,欢迎您收藏本站,我们将为您提供最新的php使用正则替换过滤掉js(script)脚本例子资源利用php中的preg_replace正则匹配函数过滤掉网页中的js代码,preg_replace()中的第四个参数中表示替换的次数,默认是-1,表示替换全部;如果只想替换2次,可以写为 preg_replace($p1,$p2,$p3,2)。

匹配的规则不能用 “//<script.*<//script>//i”,因为它不能匹配到换行符,那么多行js就匹配不掉了。要用 “//<script[sS]*?<//script>//i”。里面的?表示尽可能少重复,也就是匹配最近的一个<//script>。

源码范例:

<?php

测试php正则匹配掉js代码 测试php正则匹配掉js代码 ‘; //测试php正则匹配掉js代码 $preg = “/

 header(“Content-type:text//html;charset=utf-8”);

 $str = ‘<script type=”text//javascript” src=”dd.js”><//script>

测试php正则匹配掉js代码<script type=”text//javascript” src=”123.js”><//script>

<script type=”text//javascript”>

 var aa = “sdsds”;

 alert(aa);

<//script>

测试php正则匹配掉js代码’;

 www.111Cn.net


 $preg = “//<script[sS]*?<//script>//i”;

 $newstr = preg_replace($preg,””,$str,3);    ////第四个参数中的3表示替换3次,默认是-1,替换全部

 echo $newstr;


?>

【微信小程序】小程序webview业务域名配置、提示不支持打开非业务域名等问题

webview标签是一个内置组件,用途:承载网页的容器。会自动铺满整个小程序页面。

谨记:个人类型的小程序暂不支持使用。并且打开的链接必须是https开头的,否则还是会报错。

当你写好代码之后准备测试跳转的时候BUG出来了,它会提示你无法打开如下图

 此时你只需要进入微信公众平台

然后找到一个业务域名的配置区域就可以了,配置好域名之后你就可以,打开你要跳转的H5页面链接了。对了跳转的时候有可能会有参数和你需要新添加的参数,所以需要加密也和解密一下URL里面的参数。

加密方法:

_url = encodeURIComponent(_url);//加密,解决带参数问题

解密方法:

_url = decodeURIComponent(_url)//解密,解决url带参数问题

然后把_url传入web-view标签的src属性就可以跳转了!

iOS WebView和JS的交互

前言

现在web前端发展越来越快,为了追求应用的快速开发和迭代,许多产品都会选择混合开发,在手机端嵌入web页面,那么这就会导致一个问题,
原生代码怎么和js交互?那么下边我们共同学习一下iOS和web是怎么交互的。

概述

  1. UIWebViewJavaScriptCore的结合使用。但是我们要知道JavaScriptCore这个框架是在iOS7之后官方才发布。
  2. iOS8之后的WKWebView的使用
  3. 请求路径拦截的使用(WebViewJavascriptBridge第三方库)

我们还需要先了解一下JavaScriptCore框架的基本使用

基本使用

1、UIWebView和js的交互

OC调用js

使用UIWebviewstringByEvaluatingJavaScriptFromString方法执行js代码,或注入js代码

js调用OC

1、使用UIWebview想要js调用OC代码我们只能通过拦截的方式,代码如下:

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSString *url = request.URL.absoluteString;
    if ([url rangeOfString:@"myProtocol://"
         ].location != NSNotFound) {
        NSLog(@"拦截成功了");
        return NO;
    }
    return YES;
}

2、 在iOS7之后我们可以使用JavaScriptCore进行和js的通信

使用方式

先创建一个JSProtocol协议,遵循JSExport协议,添加一个打印方法


@protocol JSProtocol <JSExport>

-(void)print:(NSString *)str;

@end

创建一个MyJSObject对象,遵循JSProtocol,实现print方法

-(void)print:(NSString *)str
{
    NSLog(@"log=%@",str);
}

然后当web页面加载完毕的时候,通过[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]获取JSContext对象

OC代码如下:

-(void)webViewDidFinishLoad:(UIWebView *)webView
{
    self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
    
    JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    NSLog(@"context=%@",context);
    self.context = context;
    // 为js增加log方法
    context[@"log"] = ^(NSString *str){
        NSLog(@"log:%@",str);
    };
    // 为js增加obj对象 遵循该协议jsExport
    MyJSObject *obj = [[MyJSObject alloc] init];
    context[@"obj"] = obj;
    // 为js增加changeLabel的函数
    context[@"changeLabel"] = ^(NSString *str){
        self.text.text = str;
    };
    
    context.exceptionHandler = ^(JSContext *context, JSValue *exception) {
        NSLog(@"异常%@",exception);
    };
    
}

html代码

<input name="name" type="text" id="name"/>
<button onclick="changeText();">改变Label值</button>
<button onclick="printLog();">webView的js条用native(输出日志)</button>
<script type="text/javascript">
    function changeText() {
        var value = document.getElementById("name").value;
        log("输入的值="+value);
        changeLabel(value);
    }
    function printLog(str){
        // log() ,obj 是 OC提供的,执行是在ios端
        log("oc已经调用function");
        log("oc注入的方法");
        log("oc注入的obj对象"+ obj.print);
        obj.print(str);
    }
</script>

这里通过JSContextjs增加了logchangeLabel全局方法,挂载到window对象下边。当js调用log或者changeLabel方法时会执行block内的代码,当传入相应的参数,就可以达到jsOC传递参数和交互。

效果图

2、WKWebView和js的交互

WKWebViewiOS8之后才有,所以如果你的app最低支持iOS可以尽情使用。

OC调用js

使用WKWebViewevaluateJavaScript方法执行js代码,或注入js代码

js调用OC

要想WKWebViewjs交互,需要用到WKUserContentController,下面我们来看一下如何初始化WKWebView

    // 创建配置对象
    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    
    // 为WKWebViewConfiguration设置偏好设置
    WKPreferences *preferences = [[WKPreferences alloc] init];
    configuration.preferences = preferences;
    
    // 允许native和js交互
    preferences.javaScriptEnabled = YES;
    
    WKUserContentController *userContentController = [[WKUserContentController alloc] init];
    [userContentController addScriptMessageHandler:self name:@"event"];
    configuration.userContentController = userContentController;
    self.userContentController = userContentController;
    
    // 初始化webview
    WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, 300) configuration:configuration];
    // 此处替换你本机的ip
    NSURL *url = [NSURL URLWithString:@"http://172.26.233.156:3001/wkWebView"];
    webView.navigationDelegate = self;
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
    [webView loadRequest:request];
    [self.view addSubview:webView];
    self.webView = webView;

首先我们先创建WKWebViewConfiguration配置对象,然后创建WKUserContentController对象,然后我们使用WKUserContentControlleraddScriptMessageHandler
注册要接收消息的名称,这样我们才可以在js代码中通过window.webkit.messageHandlers.名称.postMessage发送消息,那么OC怎么接收消息呢?

下边是接收消息的代理

// 接受js发送的消息
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    NSLog(@"%@,%@",message.name,message.body);
    NSString *name = message.name;
    if ([name isEqualToString:@"event"]) {
        // 打开相册
        if ([message.body isEqualToString:@"打开相册"]) {
            UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
            imagePickerController.delegate = self;
            [self.navigationController presentViewController:imagePickerController animated:YES completion:nil];
        }else {
            
        }
    }
}

一定要记得在dealloc方法移除监听名称

[self.userContentController removeScriptMessageHandlerForName:@"event"];

html代码

<button onclick="openAlbum();">打开相册</button>
<script type="text/javascript">
    function openAlbum(){
        window.webkit.messageHandlers.event.postMessage("打开相册");
    }
    function testLog(str) {
        window.webkit.messageHandlers.event.postMessage(str);
        return "123"
    }
</script>

效果图

源码

源码

这里边有两个工程,一个是iOS工程,一个是node工程,用来创建一个web服务器模拟加载远程的web项目

WebViewInteractiveIOS 目录是iOS
WebViewInteractiveWeb web项目

运行

iOS运行这里不多赘述,需要注意的是把webview加载的ip换成本机ip

web运行,执行如下命令,前提是装了node环境的机器

cd WebViewInteractiveWeb
npm install 
npm run server

3、 JSBridge的使用

源码

iOS端webview和jsbridge的使用实现

首先创建一个iOS工程,引入WebViewJavascriptBridge第三方框架,使用pod还是自己手动导入都可以

下面看一下具体实现

创建WKWebview,初始化WebViewJavascriptBridge,设置WebViewJavascriptBridge,WKWebView的代理

// 初始化webview
    WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
    // 此处替换你本机的ip
    NSURL *url = [NSURL URLWithString:kHOSTURL];
    webView.navigationDelegate = self;
    webView.UIDelegate = self;
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
    [webView loadRequest:request];
    [self.view addSubview:webView];
//  self.webView = webView;
    
    self.view.backgroundColor = [UIColor whiteColor];
    // 开启日志
    [WebViewJavascriptBridge enableLogging];
    
    self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
    [self.bridge setWebViewDelegate:self];
前端js手动注册和获取JSBridge

/*这段代码是固定的,必须要放到js中*/
function setupWebViewJavascriptBridge(callback) {
    if (window.WebViewJavascriptBridge) {
        return callback(WebViewJavascriptBridge);
    }
    if (window.WVJBCallbacks) {
        return window.WVJBCallbacks.push(callback);
    }
    window.WVJBCallbacks = [callback];
    var WVJBIframe = document.createElement('iframe');
    WVJBIframe.style.display = 'none';
    WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';
    document.documentElement.appendChild(WVJBIframe);
    setTimeout(function() {
        document.documentElement.removeChild(WVJBIframe)
    }, 0)
}
// 初始化jsbridge
setupWebViewJavascriptBridge(function(bridge) {
    global.bridge = bridge;// 获取到jsbridge;
})
OC调用js

首先需要js注册交互

this.$bridge.registerhandler('ocCallJs', (data, responseCallback) => {
        alert(data)
        responseCallback(data)
    });

iOS端需要WebViewJavascriptBridge使用callHandler调用js注册的方法

[self.bridge callHandler:@"ocCallJs" data:@"123" responseCallback:^(id responseData) {
        NSLog(@"responseData=%@",responseData);
    }];

js调用OC

需要iOS注册一个交互以供js回调

[self.bridge registerHandler:@"jsCallOc" handler:^(id data, WVJBResponseCallback responseCallback) {
        //将base64字符串转为NSData
        NSData *decodeData = [[NSData alloc]initWithBase64EncodedString:data options:NSDataBase64DecodingIgnoreUnknownCharacters];
        //将NSData转为UIImage
        UIImage *decodedImage = [UIImage imageWithData: decodeData];
        TwoController *twoCtr = [[TwoController alloc] init];
        twoCtr.view.backgroundColor = [UIColor purpleColor];
        [self.navigationController pushViewController:twoCtr animated:YES];
        twoCtr.image = decodedImage;
        
        if (responseCallback) {
            // 反馈给JS
            responseCallback(@{@"jsCallOc的参数1": @"jsCallOc的参数2"});
        }
    }];

js调用交互

this.$bridge.callhandler("jsCallOc",image.replace("data:image/jpeg;base64,",""),(responseData)=>{
          console.log("responseData",responseData);
        })

效果图

1.gif

作者:小猿_Luck_Boy
链接:https://www.jianshu.com/p/3fea43b882eb
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

IOS WebView中JS和OC相互调用

现在有很多项目中都涉及到HTML5,在一个普通的APP里面嵌入HTML5网页,嵌入的这些网页在服务器把页面修改之后同样也能跟着修改,这样就能很方便的修改程序的展示内容。如果使用tabelView或者其他的控件展示内容的话,当展示的内容的样式需要发生改变的时候必须修改程序本身才能够达到修改的效果。所以,在APP里面HTML5的嵌入可以更加方便的维护程序的内容,但是由于现在受网速啊,手机性能等因素的影响导致HTML5的用户体验没有系统原生代码修改的APP好,所以针对这个JS和OC的项目调用,这里只是简单的讲讲,方便大家以后的学习和使用。


1.JS调OC

  在JS调用OC的时候,其实我使用的是取巧的办法,当我们使用webView加载网页的时候,每一次请求都会被webView的

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;

代理方法捕捉到,然后我们就可以在该代理方法里面进行相应的操作,这里我们先看看我写的一个简单测试代码,首先看测试网页的源代码:

<html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <br/><br/>
    <button onclick="fn_call();">打电话</button>
    <br/><br/>
    <button onclick="fn_getmethon();">获取参数</button>
    <script type="text/javascript">
    function fn_call(){
        window.location.href='sn://call';
    }
    function fn_getmethon(){
        window.location.href='sn://getValue';
    }
    function fn_alertMsg(msg){
        alert(msg);
    }
    </script>
    </body>
</html>

在这个页面里面,有两个按钮,按钮点击之后分别调用两个方法,在方法里面使用window.location.href='sn://getValue'发送一个请求,但是这个请求的协议不是http所以页面不会进行跳转;接着我们在webView的代理方法里面捕捉事件。

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    NSString *url = request.URL.absoluteString;
    NSLog(@"打印请求的URL-->%@", url);
    NSRange range = [url rangeOfString:@"sn://"];
    NSUInteger location = range.location;
    if (location != NSNotFound) {
        NSString *methon = [url substringFromIndex:location + range.length];
        SEL fn = NSSelectorFromString(methon);
        [self performSelector:fn withObject:nil];
    }

    return YES;
}

- (void)call {
    NSLog(@"调用打电话");
}
这里写图片描述

当我们按了”打电话”这个按钮之后,控制台就会出现

这里我们就可以对得到的URL进行简单的截取啊,判断等操作,然后再执行需要执行的OC代码,我这里是调用了call()这个方法,这样就完成了JS对OC的调用。

2.OC调JS

  前面讲了JS对OC的调用,在这里OC调用JS的原理其实差不多,在最开始的html页面里面有一个”获取值”的按钮点击之后就会调用js方法,然后在OC里面捕捉到对应的方法

- (void)getValue {
    NSLog(@"调用获取值");
    NSMutableString *js = [NSMutableString string];
    

[js appendString:[NSString stringWithFormat:@“fn_alertMsg(‘%@’);”, @“这是测试传值”]

]; [self.webView stringByEvaluatingJavaScriptFromString:js]; }

执行结果

这这个方面里面我们主要记住要在webView执行js代码就要调用- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;这个方法,我们只需要传入需要执行的JS代码然后就可以在webView里面执行。先看看执行的效果:
通过上面提到的的代码就完成了OC对JS的调用,在用OC对JS调用的时候我们要先测试JS代码的正确性,这样能提高我们的开发效率。

  好了,webView中JS和OC调用,以及OC和JS的调用就写到这里了,有不足的地方希望大家多提提,最后附上完整的代码,webView控件使用故事版拖的

@interface ViewController () <UIWebViewDelegate>
@property (strong, nonatomic) IBOutlet UIWebView *webView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle].resourcePath stringByAppendingPathComponent:@"test.html"]];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    self.webView.delegate = self;
    [self.webView loadRequest:request];
}

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    NSString *url = request.URL.absoluteString;
    NSLog(@"打印请求的URL-->%@", url);
    NSRange range = [url rangeOfString:@"sn://"];
    NSUInteger location = range.location;
    if (location != NSNotFound) {
        NSString *methon = [url substringFromIndex:location + range.length];
        SEL fn = NSSelectorFromString(methon);
        [self performSelector:fn withObject:nil];
    }

    return YES;
}

- (void)getValue {
    NSLog(@"调用获取值");
    NSMutableString *js = [NSMutableString string];
    

[js appendString:[NSString stringWithFormat:@“fn_alertMsg(‘%@’);”, @“这是测试传值”]

]; [self.webView stringByEvaluatingJavaScriptFromString:js]; } – (void)call { NSLog(@”调用打电话”); } @end

thinkphp 数据库连接报错 SQLSTATE[HY000] [2002] No such file or directory

https://blog.csdn.net/tornge/article/details/51388233

找到mysql sokcet的路径

vim /etc/mysql/mysql.conf.d/mysqld.cnf 
socket          = /var/run/mysqld/mysqld.sock

在php.ini中关于mysql的socket路径的地方,修改如如下

复制代码
[Pdo_mysql]
; If mysqlnd is used: Number of cache slots for the internal result set cache
; http://php.net/pdo_mysql.cache_size
pdo_mysql.cache_size = 2000

; Default socket name for local MySQL connects.  If empty, uses the built-in
; MySQL defaults.
; http://php.net/pdo_mysql.default-socket
pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock

SQLSTATE[HY000] [2002] Connection refused错误 (磁盘满了导致MySQL启动不了)

问题:自己公司的测试服务器,运行的好好的,突然不能用了,数据库打不开,项目也打不开,报SQLSTATE[HY000] [2002] Connection refused,去百度了一下,发现是磁盘满了MySQL启动不了导致的,后来查看了一下,发现是因为mysql_bin日志自动生成

查看占用磁盘空间的文件

清除日志后,查看文件大小

然后自己根据百度的删除日志方法,将不要的日志删除(下面是别人的方法,可行的)

https://blog.csdn.net/ck3207/article/details/76691904
https://blog.csdn.net/caokun_8341/article/details/78868844

然后关闭了my.cnf里面的日志生成(根据情况而定,可以设置成每几天清除一下日志)

清除日志,释放磁盘后,重启MySQL,项目就正常运行了

PHP 苹果支付校验

最近跟iOS这边对接苹果支付,商品等信息由前端访问谷歌服务器获取,支付等都由前端完成,后端则需要校验前端传过来的参数,通过后入库处理
苹果支付后返回给iOS的数据,有一串很长的base64的数据,后端只需要获取这串数据来校验

   /**IOS内购验证票据
     * @param string $receipt_data 付款后凭证
     * @param bool $sandbox 是否为沙盒
     * @param bool $transactions 仅对包含自动续订的应用收据使用此字段
     * @return mixed
     */
    public function validate_applepay($receipt_data,$sandbox=true,$transactions=false)
    {
        $jsonData = array('receipt-data' => $receipt_data, 'password' => config('apple_pay')['password'],'exclude-old-transactions'=>$transactions);
        $post_json = json_encode($jsonData);
        $url=$sandbox===true?"https://sandbox.itunes.apple.com/verifyReceipt":"https://buy.itunes.apple.com/verifyReceipt";
        $client=new Client(['verify' => false]);
        $response=   $client->post($url,[
            'body'=>$post_json,
            'headers'  => [
                'Content-Type' => 'application/json'
            ]
        ]);
        $result= $response->getBody()->getContents();;
        $res= json_decode($result, true);
     if (intval($res['status']) == 0) {  //验证成功
            $apple_pay = config('apple_pay');
            $products = array_keys($apple_pay['products']);
            $product_id = $res['receipt']['in_app'][0]['product_id'];
            if (!in_array($product_id, $products)) {
                $this->error='不是系统内部的商品ID';
                return false;
            }
            if ($res['receipt']['bundle_id']!= $apple_pay['bundle_id']) {
                $this->error='bundle_id 不一致';
                return false;
            }
            $info = $this->getOne($res['receipt']['in_app'][0]['transaction_id']);
            if ($info){
                $this->error='交易号重复';
                return false;
            }
            return true;
        } elseif (intval($res['status']) == 21007) {
            return  $this->validate_applepay($receipt_data,true);
        } else {
            $this->error=self::code[$res['status']];
            return false;
        }
    }

校验通过后,苹果返回的状态码

 Const code=[
        21000=>'App Store无法读取你提供的JSON数据',
        21002=>'收据数据不符合格式',
        21003=> '收据无法被验证',
        21004=> '你提供的共享密钥和账户的共享密钥不一致',
        21005=> '收据服务器当前不可用',
        21006=> '收据是有效的,但订阅服务已经过期。当收到这个信息时,解码后的收据信息也包含在返回内容中',
        21007=>'收据信息是测试用(sandbox),但却被发送到产品环境中验证',
        21008=>'收据信息是产品环境中使用,但却被发送到测试环境中验证'
    ];

校验通过的返回的数据

    "receipt":{
        "receipt_type":"ProductionSandbox",
        "adam_id":0,
        "app_item_id":0,
        "bundle_id":"com.xxx.xxx",
        "application_version":"2",
        "download_id":0,
        "version_external_identifier":0,
        "receipt_creation_date":"2020-07-03 03:05:51 Etc/GMT",
        "receipt_creation_date_ms":"1593745551000",
        "receipt_creation_date_pst":"2020-07-02 20:05:51 America/Los_Angeles",
        "request_date":"2020-07-09 03:26:37 Etc/GMT",
        "request_date_ms":"1594265197186",
        "request_date_pst":"2020-07-08 20:26:37 America/Los_Angeles",
        "original_purchase_date":"2013-08-01 07:00:00 Etc/GMT",
        "original_purchase_date_ms":"1375340400000",
        "original_purchase_date_pst":"2013-08-01 00:00:00 America/Los_Angeles",
        "original_application_version":"1.0",
        "in_app":[
            {
                "quantity":"1",
                "product_id":"xxxx",
                "transaction_id":"1000000687969364",
                "original_transaction_id":"1000000687969364",
                "purchase_date":"2020-07-03 03:05:51 Etc/GMT",
                "purchase_date_ms":"1593745551000",
                "purchase_date_pst":"2020-07-02 20:05:51 America/Los_Angeles",
                "original_purchase_date":"2020-07-03 03:05:51 Etc/GMT",
                "original_purchase_date_ms":"1593745551000",
                "original_purchase_date_pst":"2020-07-02 20:05:51 America/Los_Angeles",
                "is_trial_period":"false"
            }]
    },
    "status":0,
    "environment":"Sandbox"
}

作者:seahonest
链接:https://www.jianshu.com/p/02a4fa66b9cf
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。