当前位置:首页 > 游戏 >

苹果怎么设置游戏支付(苹果手机游戏支付怎么设置)

来源:原点资讯(www.yd166.com)时间:2023-10-29 04:17:07作者:YD166手机阅读>>

iOS 11 用户可以在 App Store 内 App 的下载页面内直接购买应用的内购商品,这项功能苹果称作做 Promoting In-App Purchases,如果你的 App 需要在 App Store 推广自己的内购商品,则需要在上图的 App Store 推广 里上传推广用的图像,另外苹果也在 iOS11 SDK 里面新增了从 App Store 购买内购项目跳转到 App 的新方法

配置沙箱测试账号

内购也是需要测试的,但是内购涉及到钱,所以苹果为内购测试提供了 沙箱测试账号 的功能,Apple Pay 推出之后 沙箱测试账号 也可以用于 Apple Pay 支付的测试,沙箱测试账号 简单理解就是:只能用于内购和 Apple Pay 测试功能的 Apple ID,它并不是真实的 Apple ID,下面看如何创建 沙箱测试账号

Itunes Connect 后台选择 用户和职能,选择 添加测试账号

苹果怎么设置游戏支付,苹果手机游戏支付怎么设置(5)

苹果怎么设置游戏支付,苹果手机游戏支付怎么设置(6)

填写沙箱测试账号信息需要注意以下几点:

  • 电子邮件不能是别人已经注册过 AppleID 的邮箱
  • 电子邮箱可以不是真实的邮箱,但是必须符合邮箱格式
  • App Store 地区的选择,测试的时候弹出的提示框以及结算的价格会按照沙箱账号选择的地区来,建议测试的时候新建几个不同地区的账号进行测试

配置好测试账号之后,看一下沙箱账号测试的时候如何使用:

  • 首先沙箱测试账号必须在真机环境下进行测试,并且是 adhoc 证书或者 develop 证书签名的安装包,沙盒账号不支持直接从 App Store 下载的安装包
  • 去真机的 App Store 退出真实的 Apple ID 账号,退出之后并不需要在App Store 里面登录沙箱测试账号
  • 然后去 App 里面测试购买商品,会弹出登录框,选择 使用现有的 Apple ID,然后登录沙箱测试账号,登录成功之后会弹出购买提示框,点击 购买,然后会弹出提示框完成购买

苹果怎么设置游戏支付,苹果手机游戏支付怎么设置(7)

上面说了这么多只是集成内购的一些准备,真正重要的是下面的内购代码的实现

iOS 内购具体代码

写代码之前先来了解对比一下 IPA 和支付宝支付,首先看支付宝的支付流程:

  • App 发起一笔支付交易,然后服务端根据支付宝的要求把订单信息进行加密签名
  • 服务端把加密的交易信息返回给 App,App 拿到交易信息调用支付宝的 SDK,把支付信息给到支付宝的服务端验证
  • 验证通过后,App 跳转到支付宝 App 或者网页版支付宝,用户使用支付宝进行支付
  • 支付成功后从支付宝 App 跳转回到我们自己 APP,我们在 App 里处理回调结果刷新UI等
  • 同时支付宝的服务器也会回调我们自己服务器,把收据传给服务器,支付宝服务器会一直回调我们的服务器直到我们的服务器确认收到收据
  • 我们的服务器收到回调确认之后,确认订单支付成功
  • 为了以防万一,App 上回调返回成功之后我们还需要去自己服务器验证是否真的支付成功(一切以服务器为准)

微信支付和支付宝支付的流程是类似的,来看看 IAP 的支付流程:

  • App 发起一笔内购支付,然后服务端生成一个订单号并且返回给 App
  • App 拿到交易订单之后调用 IPA 创建一个 IPA 交易,并且添加到支付队列
  • 然后 IAP 会调用 Apple ID 支付页面等待用户确认支付,IPA 和苹果自己的 IPA 服务器通讯,回调购买成功,并且把收据写入 App 沙盒
  • 然后 App 去沙盒获取收据并且上传到自己的服务器
  • 服务器去 IAP 服务器查询收据的有效性并且对应到某个订单号,如果有效就通知 App,并且发放该内购商品,App 调用IAP 支付队列去结束该 IPA 交易

对比来看两者区别好像也不大,支付宝或者微信支付,一旦App 端支付成功,之后的验证工作就完全是我们的服务器和支付宝服务器之前的通讯了,服务端之间的通讯就保证了交易的可靠性,但是看看 IAP,同样的交易,服务端的验证却需要 App 端去驱动,由于 App 的网络环境比服务端复杂、用户操作的不确定性可能会导致 APP 无法正确的驱动服务端验证交易,另一方面 IAP 的服务器在美国,验证查询交易的延迟也很严重

苹果 IAP 的那些坑后面再讲,先按照上面的流程,我们把 IPA 代码的逻辑理一理:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120

import UIKitimport StoreKitclass ViewController: UIViewController, SKProductsRequestDelegate,SKPaymentTransactionObserver { override func viewDidLoad() { super.viewDidLoad() // 监听支付队列 SKPaymentQueue.default().add(self as SKPaymentTransactionObserver) } deinit { SKPaymentQueue.default().remove(self as SKPaymentTransactionObserver) } // 点击购买 @IBAction func buy(_ sender: UIButton) { if SKPaymentQueue.canMakePayments() { requestProductInfo("com.xiaovv.IAPDemo.vip1") }else { print("用户禁止购买") } } // 请求查询 iTunes Connect 后台配置的内购商品 Fileprivate func requestProductInfo (_ productId: String) { let identifiers: Set<String> = [productId] let request = SKProductsRequest(productIdentifiers: identifiers) request.delegate = self request.start() } fileprivate func transcationPurchasing(_ transcation: SKPaymentTransaction) { print("交易中...") } fileprivate func transcationPurchased(_ transcation: SKPaymentTransaction) { print("交易成功...") // 持久化订单信息 if let receiptUrl = Bundle.main.appStoreReceiptURL {//获取收据地址 let receipt = NSData(contentsOf: receiptUrl) let receiptStr = receipt?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)) DispatchQueue.main.asyncAfter(deadline: DispatchTime(uptimeNanoseconds: 3)) {// 模拟上传收据到服务端 print("receiptStr:\(String(describing: receiptStr))") print("applicationUsername:\(String(describing: transcation.payment.applicationUsername))") // 收据发送到服务器 // 收据验证成功之后结束交易 SKPaymentQueue.default().finishTransaction(transcation) // 删除保存的订单信息 } } } fileprivate func transcationFailed(_ transcation: SKPaymentTransaction) { print("交易失败...") } fileprivate func transcationRrestored(_ transcation: SKPaymentTransaction) { print("已经购买该商品...") } fileprivate func transcationDeferred(_ transcation: SKPaymentTransaction) { print("交易延期...") } //MARK: - SKPaymentTransactionObserver // 购买内购商品之后会调用的代理方法 func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { for transcation in transactions { switch (transcation.transactionState) { case .purchasing: transcationPurchasing(transcation) case .purchased: transcationPurchased(transcation) case .failed: transcationFailed(transcation) case .restored: transcationRrestored(transcation) case .deferred: transcationDeferred(transcation) } } } //MARK: - SKProductsRequestDelegate // 查询iTunes Connect 后台内购商品的回调代理方法 func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { if response.products.count > 0 { let payment = SKMutablePayment(product: response.products.first!) // applicationUsername 可以把我们的自己订单和IAP的交易订单绑定 payment.applicationUsername = "orderid,userid and so on" }else { print("没有可以购买的商品") } }}

IAP 的代码看起来并不多流程也比较清晰,主要是下面几步:

  • 根据内购商品的产品 ID 初始化一个 SKProductsRequest 对象,调用该对象的 start() 方法进行内购商品的请求
  • 把商品请求中获取到的 SKProduct 对象生成一个 SKPayment 对象,并把它压入到 SKPaymentQueue 支付队列中
  • 然后从支付队列的代理方法 func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) 里面获取到交易(transaction)的状态,交易完成后调用支付队列的 finishTransaction()完成内购支付
iOS 内购减少丢单处理

上面说到 IAP 的坑,下面就列举一下 IAP 留给开发者的 “坑”:

  1. 用户输入完 Apple ID 密码或者验证完指纹支付成功之后,网络突然中断导致 IAP 没有收到支付成功的通知,App 就无法在支付队列的代理方法中获取支付成功的通知,后续的发放内购商品也就不可能了
  2. App 在代理方法里收到了支付成功的通知,但是 App 上传交易收据到我们服务器去查询的时候如果查询失败,那么服务器就无法发放内购商品,因为这个行为是 App 驱动服务器的行为,这里有个坑就是支付队列的代理方法 func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) 需要下次 App 重新启动才会重新调用,这个时候我们 App 才能重新去驱动服务器查询交易,由于用户操作的不确定性,不知道什么时候用户才会重新打开App,发放内购商品的周期自然也不确定
  3. 之前有开发者反应,IAP 通知代理方法交易成功,但是沙盒里面取收据的时候发现为空,或者当前支付成功的订单并没有写入沙盒的收据,导致上传到服务器的收据查询不到结果
  4. 如果用户支付成功,收据也上传服务器成功,但是在服务器验证阶段用户删除了App,导致App 无法去处理这些没有被验证完的订单
  5. 如何处理越狱iOS手机内购的问题

以上问题都可能会导致用户支付成功了,却收不到我们发放的内购商品,统一起来称为:内购丢单

接下来讨论一下如何处理 IAP 支付的一些细节问题克服上述 IAP 的坑

越狱问题

我本人也折腾过 iOS 越狱,安装实用插件、美化主题等,自从iOS 9 之后越狱社区越来越不活跃了,能完美越狱的基本都是iPhone 5 以及更老的 32位设备了,这也侧面也说明了 iOS 在功能方面已经非常完善了,导致折腾越狱的人越来越少了,当前 iOS 版本是否越狱可以去这个网站查看:Can I jailbreak

回归正题,因为越狱之后会导致系统不确定的问题很多,我觉得可以采用宁可错*一千也不放过一个原则,对于已越狱的iOS 设备全部不允许内购行为,简单粗暴有效,可以通过下面工具的方法判断iOS设备是否越狱

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114

.h 文件#import <Foundation/Foundation.h>@interface JailbreakDetectTool : NSObject/** * 检查当前设备是否已经越狱。 */ (BOOL)detectCurrentDeviceIsJailbroken;@end.m 文件#import "JailbreakDetectTool.h"#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])@implementation JailbreakDetectTool// 四种检查是否越狱的方法, 只要命中一个, 就说明已经越狱. (BOOL)detectCurrentDeviceIsJailbroken { BOOL result = NO; result = [self detectJailBreakByJailBreakFileExisted]; if (!result) { result = [self detectJailBreakByAppPathExisted]; } if (!result) { result = [self detectJailBreakByEnvironmentExisted]; } if (!result) { result = [self detectJailBreakByCydiaPathExisted]; } return result;}/** * 判定常见的越狱文件 * /Applications/Cydia.app * /Library/MobileSubstrate/MobileSubstrate.dylib * /bin/bash * /usr/sbin/sshd * /etc/apt * 这个表可以尽可能的列出来,然后判定是否存在,只要有存在的就可以认为机器是越狱了。 */const char* jailbreak_tool_pathes[] = { "/Applications/Cydia.app", "/Library/MobileSubstrate/MobileSubstrate.dylib", "/bin/bash", "/usr/sbin/sshd", "/etc/apt"}; (BOOL)detectJailBreakByJailBreakFileExisted { for (int i = 0; i<ARRAY_SIZE(jailbreak_tool_pathes); i ) { if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithUTF8String:jailbreak_tool_pathes[i]]]) { NSLog(@"The device is jail broken!"); return YES; } } NSLog(@"The device is NOT jail broken!"); return NO;}/** * 判断cydia的URL scheme. */ (BOOL)detectJailBreakByCydiaPathExisted { if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://"]]) { NSLog(@"The device is jail broken!"); return YES; } NSLog(@"The device is NOT jail broken!"); return NO;}/** * 读取系统所有应用的名称. * 这个是利用不越狱的机器没有这个权限来判定的。 */#define USER_APP_PATH @"/User/Applications/" (BOOL)detectJailBreakByAppPathExisted { if ([[NSFileManager defaultManager] fileExistsAtPath:USER_APP_PATH]) { NSLog(@"The device is jail broken!"); NSArray *applist = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:USER_APP_PATH error:nil]; NSLog(@"applist = %@", applist); return YES; } NSLog(@"The device is NOT jail broken!"); return NO;}/** * 这个DYLD_INSERT_LIBRARIES环境变量,在非越狱的机器上应该是空,越狱的机器上基本都会有Library/MobileSubstrate/MobileSubstrate.dylib. */char* printEnv(void) { char *env = getenv("DYLD_INSERT_LIBRARIES"); return env;} (BOOL)detectJailBreakByEnvironmentExisted { if (printEnv()) { NSLog(@"The device is jail broken!"); return YES; } NSLog(@"The device is NOT jail broken!"); return NO;}@end

储存交易订单

上述第1、2点坑都是因为交易订单支付成功了,但是没有完成服务器验证收据,所以我们非常有必要持久化我们的订单信息,IAP 支付成功的交易(transaction)只要没有调用 finishTransaction(),下次启动 App 重新监听支付队列的时候会重新调用 func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) 这个时候就可以重新获取到未完成的该交易(transaction)

支付成功后,我们持久化自己订单信息的目的就是和 IAP的交易(transaction)绑定起来,这样如果在App驱动服务器验证订单的时候出现了异常,App重新启动之后我们获取到未完成的 IAP的交易(transaction)之后依然可以和我们自己的订单联系起来,然后可以继续发送给后台服务器去去验证,直到验证成功完成 IAP 交易(transaction),购买结束

这里我的做法是:用户支付成功之后用 UserDefault 把该交易的交易标识(transactionIdentifier)和我们自己的交易订单作为字典的键值保存在沙盒内,然后把我们自己的订单号和支付收据发送给服务器去验证,服务器返回验证结果之后,删除 UserDefault 中的订单信息,并且完成该笔IAP 交易(transaction),如果在服务器返回验证结果之前出现异常(用户*掉App、手机关机了,App崩溃等)订单信息便不会从UserDefault 中删除,该笔IAP 交易也不会被完成,App重新启动之后,重新监听支付队列的时候,可以重新获取到该笔交易(transaction),然后根据该笔交易(transaction)的交易标识(transactionIdentifier)找到 UserDefault 中对应的我们自己的订单号,重新把订单号和交易收据发送给后台服务器验证

我们自己的订单是后台生成并且和用户ID进行了绑定的,所以这里不担心用户支付成功之后,切换 App 账号会把内购商品发放给另一个用户

我的做法比较简单,实际上用户如果删除 App,UserDefault 的订单信息就会丢失,所以订单信息储存在钥匙串 keychain 才是相对最稳妥的,特别是如果你的项目以内购为主并且支付非常频繁,这里可以参看贝聊的做法 贝聊 IAP 实战之见坑填坑

applicationUsername

由于 IAP 支付成功之后我们只能从 IAP 的代理方法里面获取到支付成功的交易(transaction),所以我们就必须把自己的订单号和对应的 IAP 交易(transaction)绑定在一起,IAP 创建 SKPayment 对象,并把它压入到SKPaymentQueue 支付队列的时候,我们可以使用可变的 SKMutablePayment,它有一个属性叫做 applicationUsername,这个属性就可以用来储存我们自己生成的订单号信息,用户支付成功之后可以成功的交易(transaction)的 payment 中获取到绑定的订单号信息,这样就可以完美的把 IAP交易(transaction)和我们自己的订单号绑定在一起了

但是,但是!苹果在这个属性上面有个巨坑,前面说到如果某个IAP交易(transaction)支付成功但是并没有调用 finishTransaction()去完成这个交易的时候,下次启动 App 重新监听支付队列的时候会重新调用 func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) 这个时候就可以重新获取到这个未完成的交易(transaction),苹果的坑就是这个时候获取 transaction 的 payment 的 applicationUsername 会出现 nil 的情况,所以实际开发中不能完全去相信这个 applicationUsername 属性,这也是为什么上面我要把自己的订单号和 IAP 交易(transaction)的交易标识持久化下来的原因

其他错漏问题

第3点坑,用户支付成功之后从沙盒获取收据为空,IAP 提供了一个SKReceiptRefreshRequest类,通过这个类可以在收据无效或者丢失的时候申请到新的收据,SKReceiptRefreshRequest继承自 SKRequest 和 SKProductsRequest 都遵循 SKRequestDelegate

第4点坑,如果我们的订单信息是持久化到钥匙串中,那么即使 App 被删除,下次重新安装的时候依然可以拿到持久化的订单信息

实际上即使把上面的问题全部考虑到了依然还可能出问题,比如用户切换了 Apple ID 这个时候钥匙串里持久化的订单信息也会发生改变、或者验证成功之前用户换新的手机登录或者用户其他的不可预知的操作行为依然会导致错漏单的问题,但是我觉得内购大部分时候是用户一种强意识的行为,上面这些操作只能是认为用户在阻止自己购买成功,所以我们最终是无法百分之百避免错漏单的,手动去处理这些订单是非常有必要的

IAP 服务端的处理

前面说到用户支付成功之后,我们拿到沙盒的收据信息去苹果的 IAP 服务器去验证,这里既可以直接在 App 端验证也可以让服务器去验证,实际上根据我的测试,App 端直接去IAP服务器验证比较快,毕竟中间少了很多步骤,但是考虑到越狱的 iOS 设备完全可以在系统层面跳过或者伪造收据,早期的 iOS 开发很多公司都是采用都是这种本地验证,但是现在基本都是通过后台验证的方式,具体的后台验证步骤如下:

  • App端拿到沙盒的收据(receipt-data),进行一次base64编码,上传给服务器
  • 服务器拿到收据之后发到 IAP 服务器去验证,验证成功之后收据需要和自己的订单号进行映射并且记录在数据库,之后每次验证之前都需要先判断收据是否存在,防止 App 端重复上传相同的收据,重复发放内购商品
  • 服务器发放内购商品,推送通知给用户等

由于 App 上线 App Store 之前我们是使用沙盒账号测试的,沙盒测试的收据验证也是要去沙盒收据的服务器验证

  • 沙盒环境验证服务器:https://sandbox.itunes.apple.com/verifyReceipt
  • 正式环境验证服务器:https://buy.itunes.apple.com/verifyReceipt

而且苹果在上线审核的时候也是使用沙盒账号测试的,那如何识别App端发过来的收据是沙盒测试还是正式环境用户的购买呢?这里服务端就要采用双重验证,即先把收据拿到正式环境的验证地址去验证,如果苹果的正式环境验证服务器返回的状态码 status 为 21007,则说明当前收据是沙盒环境产生,则再连接一次沙盒环境服务器进行验证,这样不管是我们自己采用沙盒账号测试还是苹果审核人员采用沙盒账号进行审核、或者用户购买都可以保证收据正常的验证成功

沙盒测试遇到的其他问题
  • 在进行沙盒测试的时候,遇到过 IAP 沙盒服务器出现异常,购买过程非常的慢,而且总是超时,返回购买失败,谷歌到有同行也出现过沙盒购买缓慢的问题(iTunes Sandbox Extremely Slow),所以如果确定代码没有问题,多半就是 IAP 的沙盒服务器出现了问题,建议换个时间再测试,可以通过 System Status - Apple Developer 查看苹果公司开发者相关的服务的服务状态
  • 如果内购的时候提示 您已购买此 App 内购买项目。此项目将免费恢复。,说明有一个购买了同一商品 IAP 交易(transaction)没有调用 finishTransaction()去结束这个交易
Promoting In-App Purchases

前面提到iOS 11 之后,开发者可以在 App Store 自己App的下载页面推广自己的内购商品,用户可以直接在App下载页面购买内购商品,这就涉及到从App Store跳转到自己App,所以苹果在 SKPaymentTransactionObserver 新增了一个代理方法:

12345

func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment payment: SKPayment, for product: SKProduct) -> Bool { return false}

用户如果在 App下载页面点击购买你推广的内购商品,如果用户已经安装过你的 App 则会直接跳转你的App并调用上述代理方法;如果用户还没有安装你的 App 那么就会去下载你的 App,下载完成之后系统会推送一个通知,如果用户点击该通知就会跳转到你的App并且调用上面的代理方法

上面的代理方法返回 true 则表示跳转到你的 App,IAP 继续完成交易,如果返回 false 则表示推迟或者取消购买,实际开发中因为可能还需要用户登录自己的账号、生成订单等,一般都是返回 false,之后自己手动把代理方法里面返回的 SKPayment 加入支付队列,然后在按照自己的支付、验证逻辑完成支付

以上就是我做内购的时候从网上的资料以及官方文档总结的一些东西

参考和推荐阅读:

iOS内购一条龙——账户信息填写

苹果应用内购买(IAP)—从入门到放弃

iOS 贝聊 IAP 实战之满地是坑

苹果IAP开发中的那些坑和掉单问题

Receipt Validation Programming Guide

In-App Purchase Programming Guide

收据验证编程指南

iOS内购充值 服务器端处理

iOS 内购服务器验票(漏单处理)


作者:Hsiaovv

出处:https://xiaovv.me/2018/05/03/My-iOS-In-App-Purchase-Summarize/

上一页12末页

栏目热文

和平精英第三方充值平台(和平精英可以第三方充值吗)

和平精英第三方充值平台(和平精英可以第三方充值吗)

上个月,视觉中国曾因 黑洞照片、国徽、各大企业logo等版权问题遭到痛批,并进行下线停牌整顿,网站经过一个月的关停后,其...

2023-10-29 03:31:38查看全文 >>

微信怎么关闭游戏充值(如何关闭微信游戏充值功能)

微信怎么关闭游戏充值(如何关闭微信游戏充值功能)

自动续费冤大头。什么自动续费霸王条款,买完降价,多交的冤枉钱其实都能退!看完这个视频你可赚大了!找谁退?自动续费可以在支...

2023-10-29 03:31:09查看全文 >>

苹果怎么用支付宝充值游戏(iphone充值游戏怎么用支付宝)

苹果怎么用支付宝充值游戏(iphone充值游戏怎么用支付宝)

米哈游支付中心小程序现已上线支付宝,无需登录游戏就能进行充值操作,绑定《原神》、《崩坏:星穹铁道》、《崩坏3》游戏账号所...

2023-10-29 03:45:54查看全文 >>

苹果手机用微信充值和平精英(苹果手机怎么直接充值和平精英)

苹果手机用微信充值和平精英(苹果手机怎么直接充值和平精英)

2022年1月31日,农村妇女郭某为和儿子过个年,将与前夫生活的儿子带回老家,在做饭待客的功夫,11:59起6岁小孩在客...

2023-10-29 03:58:16查看全文 >>

苹果如何在微信充值和平精英(苹果和平精英微信充值步骤)

苹果如何在微信充值和平精英(苹果和平精英微信充值步骤)

9月25日,湖南岳阳市民熊女士告诉潇湘晨报(报料微信:xxcbbaoliao)晨意帮忙记者,今年7月,她发现13岁的儿子...

2023-10-29 03:30:36查看全文 >>

wipes是男士湿巾么(男士抑菌湿巾是啥)

wipes是男士湿巾么(男士抑菌湿巾是啥)

【关注我,每天更新英语趣味知识】夏天真是越来越热了,包包里除了放手帕纸,湿纸巾也成了必备物烈日炎炎下,用湿纸巾擦擦手、脸...

2023-10-29 04:15:53查看全文 >>

印度湿巾怎么使用图解(印度湿巾的正确使用方法)

印度湿巾怎么使用图解(印度湿巾的正确使用方法)

很多去过印度的游客都会在卫生间的马桶旁边看到一根“奇怪”的软管,那么,这根软管到底是用来干什么的呢?图片来源:新浪网友@...

2023-10-29 03:51:00查看全文 >>

湿巾哪个牌子的好(湿巾哪个牌子好用便宜)

湿巾哪个牌子的好(湿巾哪个牌子好用便宜)

本内容来源于@什么值得买APP,观点仅代表作者本人 |作者:小泽不是玛利亚o0Hi呀~我是新晋宝妈小泽!马上小小泽就满月...

2023-10-29 04:09:57查看全文 >>

wipes湿巾好不好(杀菌湿巾推荐测评)

wipes湿巾好不好(杀菌湿巾推荐测评)

编者按:很多时候,一项产品的使用,其实远不单纯地受到科技的影响,它也会受到社会风气,人们偏见的制约。还记得你从日本千里迢...

2023-10-29 04:13:25查看全文 >>

老爸评测婴儿湿巾(婴儿湿巾含甲醛名单)

老爸评测婴儿湿巾(婴儿湿巾含甲醛名单)

育儿路上,大到一罐奶粉,小到一纸湿巾,都是奶爸奶妈们劳神操心的对象。消道长也不敢闲着,本期就带来爸妈们关心的婴儿湿巾测评...

2023-10-29 04:14:54查看全文 >>

文档排行