扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
Flutter是一个移动应用程序的软件开发工具包(SDK),具有以下特征:
元宝ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为成都创新互联的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:028-86922220(备注:SSL证书合作)期待与您的合作!
跨平台应用的框架,没有使用WebView或者系统平台自带的控件,使用自身的高性能渲染引擎自绘
简化版的浏览器,最大限度在android和ios上统一UI,包括业务逻辑和用户体验
开发语言使用dart,结合C, C++, 和Skia(2D渲染引擎)构建
支持hot reload,包含着完整的控件和工具链
一切皆控件,控件是每个Flutter应用程序的基本构建块,与分离视图、控制器、布局和其他属性的框架不同,Flutter具有一致的统一对象模型:控件。一个控件可以定义:结构元素(比如按钮或菜单)、风格元素(比如字体或颜色方案)、布局的方面(比如填充)、一些业务逻辑等
组合大于继承,控件本身通常由许多小型、单用途的控件组成,结合起来产生强大的效果,类的层次结构是扁平的,以最大化可能的组合数量
强化版的WebView,框架仅提供一个View层,大部分功能要依赖原生
目前只能够运行大部分Dart代码(不能引入dart:mirrors或dart:html库)
1、先建立模型
将json数据转化为dart
2、创建provide
import 'package:flutter/material.dart';
import '../model/details.dart';
import '../service/service_method.dart';
import 'dart:convert';
class DetailsInfoProvidewith ChangeNotifier {
//model
DetailsModelgoodsInfo =null;
// 从后台获取商品数据
getGoodsInfo(String id)async{
var formData = {'goodId': id};
await request('getGoodDetailById', formData: formData).then((value) {
// 将获得的数据转换为对象
var responseData=json.decode(value.toString());
// print(responseData);
// 将获得的数据转换为模型
goodsInfo=DetailsModel.fromJson(responseData);
// 通知监听者
notifyListeners();
});
}
3、全局注入 在main.dart中
var providers =Providers();
var detailsInfoProvide =DetailsInfoProvide();
// 将状态放入顶层
providers
..provide(Provider.value(counter))
..provide(Provider.value(childCategory))
..provide(Provider.value(categoryGoodsListProvide))
..provide(Provider.value(detailsInfoProvide));
4、在页面引入privide
//调用provide时需要context
void _getBackInfo(BuildContext context)async{
await Provide.value(context).getGoodsInfo(goodsId);
}
5、进行页面ui搭建
Widget build(BuildContext context) {
return Scaffold(
appBar:AppBar(
leading:IconButton(icon:Icon(Icons.arrow_back), onPressed: (){
Navigator.pop(context);
}),
title:Text('商品详情页'),
),
body:FutureBuilder(
future: _getBackInfo(context),
builder: (context, snapshot) {
// 是否返回值
if (snapshot.hasData) {
return Container(
child:Column(
children: [
Text(goodsId)
],
),
);
}else{
return Text("加载中。。。。");
}
}
),
);
}
//调用provide时需要context
Future _getBackInfo(BuildContext context)async{
await Provide.value(context).getGoodsInfo(goodsId);
return "完成加载";
}
6、新建与页面同名的文件夹进行拆分
//需要用到provide数据的
import 'package:flutter/material.dart';
import 'package:flutter_shop/config/font.dart';
import 'package:provide/provide.dart';
import '../../provide/details_info.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class DetailsTopAreaextends StatelessWidget {
@override
Widget build(BuildContext context) {
return Provide(
builder: (context,child,val){
var goodsInfo=Provide.value(context).goodsInfo.data.goodInfo;
if(goodsInfo!=null){
return Container(
color: Colors.white,
child:Column(
children: [
_goodsImage(goodsInfo.image1),
_goodsName(goodsInfo.goodsName),
_goodsNum(goodsInfo.goodsSerialNumber),
_goodsPrice(goodsInfo.presentPrice,goodsInfo.oriPrice)
],
),
);
}else{
return Text("正在加载中");
}
}
);
}
// 商品图片
Widget _goodsImage(url){
return Image.network(url,width:ScreenUtil().setWidth(740),);
}
// 商品名称
Widget _goodsName(name){
return Container(
width:ScreenUtil().setWidth(740),
padding:EdgeInsets.only(left:15.0),
child:Text(name,
style:TextStyle(
fontSize:ScreenUtil().setSp(30),
),
),
);
}
// 商品编号
Widget _goodsNum(num){
return Container(
width:ScreenUtil().setWidth(730),
padding:EdgeInsets.only(left:15.0),
margin:EdgeInsets.only(top:8.0),
child:Text('编号:${num}',style:TextStyle(
color: Colors.black45
),),
);
}
// 价格
Widget _goodsPrice(nowPrice,oriPrice){
return Container(
width:ScreenUtil().setWidth(730),
padding:EdgeInsets.only(left:15.0),
margin:EdgeInsets.only(top:8.0),
child:Row(
children: [
Text('¥${nowPrice}',style:TextStyle(
color: Colors.red
),),
Text('市场价¥${oriPrice}',style: KFont.oriPriceStyle),
],
)
);
}
}
//不需要用的provide数据的
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class DetailExplainextends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
margin:EdgeInsets.only(top:10, bottom:10),
color: Colors.white,
width:ScreenUtil().setWidth(750),
padding:EdgeInsets.only(top:10.0,left:15,bottom:10,right:15),
child:Text(
"说明:极速送达正品保证",
style:TextStyle(color: Colors.red, fontSize:ScreenUtil().setSp(30)),
),
);
}
}
点击 “协议、税务和银行业务”
内购用的是付费应用程序,先签署《付费应用程序协议》,同意后状态变更为“用户信息待处理”,等待审核。
状态更改完毕后,点击“开始设置税务、银行业务和联系信息”。
(1)添加银行账户,按照要求填写相关内容即可。
(2)选择报税表,并填写。所有与 Apple 有商业合作者必选都是美国,若有其他需求,可以多选。
继续填写,首先认证公司基本信息,选择所有人类型,确认无误后认证条款处打对勾
Part I 部分,继续核对公司相关信息,选填内容可不填。
Part III 部分,签署税务条约,设置利益限制条款的种类,选填内容可不填。此部分如果需要可勾选上下图勾选框,不需要可不勾选,我们这个项目没有用到part III 部分,所以没有勾选。
Part XXX 部分,确认之前填写的信息,勾选完毕后,提交
(3)填写联系信息,共5个。高级管理、财务、技术、法务、营销。只需要提供5个人的基本信息即可。
只可使用一次的产品,使用之后即失效,必须再次购买。
示例: 钓鱼 App 中的鱼食。
只需购买一次,不会过期或随着使用而减少的产品。
示例: 游戏 App 的赛道。
允许用户在固定时间段内购买动态内容的产品。除非用户选择取消,否则此类订阅会自动续期。
示例: 每月订阅提供流媒体服务的 App。
允许用户购买有时限性服务的产品。此 App 内购买项目的内容可以是静态的。此类订阅不会自动续期。
示例: 为期一年的已归档文章目录订阅。
App 内购买项目的截屏,即所售项目的示意图。例如,如果 App 内购买项目是一本图书,您可以提交图书的截屏。您也可以提交购买页的截屏。该截屏仅用于 Apple 审核,不会在 App Store 中显示。
截屏要求如下:
iOS 至少需要 640 x 920 像素
Apple tvOS 需要 1920 x 1080 像素
macOS 需要 1280 x 800 像素
App 审核图像上传后,可以替换,但无法移除。当您的 App 内购买项目处于审核中时,您无法更新截屏。
沙箱账号是不能直接在App Store进行登录的,只能在点击了购买商品之后,在弹出的登录框进行登录 。
验证是否已登录沙箱测试账号:
设置--iTunes Store与App Store,页面拉到最底部,会看到沙箱账户项会列出你已登录的沙箱测试账号!
操作方法一:打开App Store应用首页滑到最下方--选中AppleID--注销
操作方法二:设置--iTunes Store与App Store--选中AppleID--注销
checks if the client can make payments(检测App是否能支付)
getAvailablePurchases
Get all non-consumed purchases 获取未消费的商品
打印信息查询;
原因:
没有先执行getProducts,直接执行requestPurchase方法,要先拉取商品列表,再执行购买操作.
问题描述;
1.漏单必须要处理,玩家花RMB购买的东西却丢失了,是绝对不能容忍的。所谓的漏单就是玩家已经正常付费,却没有拿到该拿的道具。
解决:只要购买成功,便将购买记录(receipt等账单信息)保存下来,然后将账单信息传送给我们游戏服务器,游戏服务器获得账单后,和苹果服务器验证,账单有效的话,回馈给游戏服务器处理,游戏服务器处理后,返回给游戏客户端处理,处理完毕,将本地保存的购买记录删除。
官方文档:向苹果校验支付凭证
21000 App Store无法读取你提供的JSON数据
21002 收据数据不符合格式
21003 收据无法被验证
21004 你提供的共享密钥和账户的共享密钥不一致
21005 收据服务器当前不可用
21006 收据是有效的,但订阅服务已经过期。当收到这个信息时,解码后的收据信息也包含在返回内容中
21007 收据信息是测试用(sandbox),但却被发送到产品环境中验证 【请求sandbox校验支付凭证】
21008 收据信息是产品环境中使用,但却被发送到测试环境中验证
消耗类型: 例如:金币、道具等。
非续订订阅: non-renewable subscription 例如:VIP
您的首个 App 内购买项目必须以新的 App 版本提交。请创建您的 App 内购买项目,然后前往 App 的“App Store”页,从“App 内购买项目”中进行选择,点按“提交”。 了解更多
在上传二进制文件并提交首个 App 内购买项目以供审核后,您可以使用下表提交其他 App 内购买项目。
唐巧-iOS应用内付费(IAP)开发步骤列表
未完~待续
当使用内购购买过商品之后没有把这个交易关闭,所以再次去购买商品后就会调用以前已经购买成功的交易去购买因为已经购买过,才会有这个提示
原因:添加内购项目时,信息填写不完整,app审核图像未上传
处理方法:上传app审核图片( 合适的尺寸 ),点击提交,状态改为正在准备审核中。
这个是内购选择类型不匹配原因导致。
购买成功之后,Apple会返回以下四个数据给应用
Reference
Review the updated Paid Applications Schedule.
游客身份解决方案:即不登录也要能购买
1)服务器端做一个苹果审核机制,审核期间游客身份可以进行一切行为,一旦审核通过,修改服务端即可达到强制用户登录进行内购买的目的(这个有点。。。)
2)游客可以进行内购买,购买时以设备UUID为准,生成一个游客账号,将购买信息保存在服务器和本地,当用户登录正式账户后判断此设备是否进行过内购,有的话提示用户将游客身份购买的权益与现有账号绑定,如果绑定,游客权益则迁移到正式账户,如果不迁移,则游客身份和正是账户是两个独立账户,正式账户不享有游客身份的权益(我用的这个)
内购游客模式解决方案
iOS内购规则
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流