appstore 中审核中,如果你app内卖的东西是个虚拟的产品,那么你有可能被要求不能使用第三方支付工具,只能使用 IAP 应用内支付功能。
使用这个功能需要在apple 开发者后台签合同,设置银行账号,设置价格,这个就不讲了,本篇主要讲phonegap中整合IAP的代码
/**
* 苹果应用内支付
*/
(function (cordova) {
var define = cordova.define;
define("cordova/plugin/applepay", function (require, exports, module) {
var argscheck = require('cordova/argscheck'),
exec = require('cordova/exec');
exports.pay = function (productID,quantity, successCB, failCB) {
exec(successCB, failCB, "ApplePay", "pay", [productID,quantity]);
};
});
cordova.addConstructor(function () {
if (!window.plugins) {
window.plugins = {};
}
console.log("将插件注入cordovaapplepay...");
window.plugins.applepay = cordova.require("cordova/plugin/applepay");
console.log("applepay注入结果:" + typeof (window.plugins.applepay));
});
})(cordova);
<feature name="ApplePay">
<param name="ios-package" value="CDVApplePay" />
</feature>
#import <Cordova/CDV.h>
@interface CDVApplePay : CDVPlugin
@property (nonatomic,copy) NSString*callbackID;
//Instance Method
- (void)pay:(CDVInvokedUrlCommand*)command;
@end
#import "CDVApplePay.h"
#import "AppDelegate.h"
#import <StoreKit/StoreKit.h>
#import "MainViewController.h"
#import "Conts.h"
@implementation CDVApplePay
@synthesize callbackID;
- (void)pay:(CDVInvokedUrlCommand*)command {
if ([SKPaymentQueue canMakePayments]) {
NSString *produtid = [command.arguments objectAtIndex:0];
NSString* strQuantity =[command.arguments objectAtIndex:1];
buyQuantity = [strQuantity intValue];
MainViewController* view = [[MainViewController alloc] init];
[view getProductInfo:produtid];
// [[AppDelegate appDelegate] getProductInfo:produtid];
} else {
NSLog(@"失败,用户禁止应用内付费购买.");
NSString *js = [[NSString alloc]initWithFormat:@"yooshow.alert('%@')", @"您已禁止应用内购买,请先开启" ];
[[AppDelegate appDelegate] runJS:js];
}
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@""];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
@end
MainViewController.m中添加
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// 监听购买结果
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased://交易完成
NSLog(@"transactionIdentifier = %@", transaction.transactionIdentifier);
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateFailed://交易失败
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStateRestored://已经购买过该商品
[self restoreTransaction:transaction];
break;
case SKPaymentTransactionStatePurchasing: //商品添加进列表
NSLog(@"苹果交易流水号开始交易transactionIdentifier = %@", transaction.transactionIdentifier);
NSLog(@"商品添加进列表此处我方服务器应创建订单");
break;
default:
break;
}
}
}
- (void)completeTransaction:(SKPaymentTransaction *)transaction {
// Your application should implement these two methods.
NSString * productIdentifier = transaction.payment.productIdentifier;
NSString * receipt = [transaction.transactionReceipt base64Encoding];
NSLog(@"苹果交易流水号完成交易transactionIdentifier = %@", transaction.transactionIdentifier);
if ([productIdentifier length] > 0) {
// 向自己的服务器验证购买凭证
NSLog(@"购买成功应将修改我方服务器用户数据凭证为%@,产品信息%@",receipt,productIdentifier);
NSString *js = [[NSString alloc]initWithFormat:@"pay.applePayResult('%@','%@')", transaction.transactionIdentifier,receipt];
[[AppDelegate appDelegate] runJS:js];
}
// Remove the transaction from the payment queue.
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
- (void)failedTransaction:(SKPaymentTransaction *)transaction {
if(transaction.error.code != SKErrorPaymentCancelled) {
NSLog(@"购买失败");
} else {
NSLog(@"用户取消交易");
}
NSString *js = [[NSString alloc]initWithFormat:@"$.ui.hideMask();" ];
[[AppDelegate appDelegate] runJS:js];
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
NSLog(@"恢复购买");
NSString * productIdentifier = transaction.payment.productIdentifier;
NSString * receipt = [transaction.transactionReceipt base64Encoding];
if ([productIdentifier length] > 0) {
// 向自己的服务器验证购买凭证
NSLog(@"恢复购买成功应将修改我方服务器用户数据凭证为%@,产品信息%@",receipt,productIdentifier);
}
// 对于已购商品,处理恢复购买的逻辑
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
// 下面的ProductId应该是事先在itunesConnect中添加好的,已存在的付费项目。否则查询会失败。
- (void)getProductInfo:(NSString*) productID
{
NSSet * set = [NSSet setWithArray:@[productID]];
SKProductsRequest * request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
request.delegate = self;
[request start];
}
// 以上查询的回调函数
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSArray *myProduct = response.products;
if (myProduct.count == 0) {
NSLog(@"无法获取产品信息,购买失败。");
NSString *js = [[NSString alloc]initWithFormat:@"$.ui.hideMask();" ];
[[AppDelegate appDelegate] runJS:js];
return;
}
// SKPayment * payment = [SKPayment paymentWithProduct:myProduct[0]];
// payment.quantity =buyQuantity;
SKMutablePayment * payment = [SKMutablePayment paymentWithProduct:myProduct[0]];
payment.quantity = buyQuantity;
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
注意客户端成功后的回调
最后服务端的验证,服务端我用的是 C#
public bool ApplePayNotifyVerify(ApplePayParam param)
{
//验证支付凭证
// 初始化通信处理类
try
{
//支付凭证不能被重复使用,检查支付凭证是否已经被计入流水账,如果被使用过,直接返回false, 未被使用过的才可以验证,并处理相关业务
var payment = PaymentService.Instance.GetList(p => p.AppleReceipt == param.AppleReceipt).FirstOrDefault();
if (payment == null)
{
var config = AppService.Instance.GetThirdPartyConfig();
System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var receipt = "{\"receipt-data\":\"" + param.AppleReceipt + "\"}";
HttpContent content = new StringContent(receipt, Encoding.UTF8);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = httpClient.PostAsync(new Uri(config.ApplePayVerify), content).Result;
string result = response.Content.ReadAsStringAsync().Result.Replace(Environment.NewLine, string.Empty).Replace("\n", string.Empty);
var entity= JObject.Parse(result);
//AppleVerifyEntity entity = JsonConvert.DeserializeObject<AppleVerifyEntity>(result);
if (entity.Value<int>("status") == 0)
{
//成功之后修改订单状态,记帐,加花
OrderPaySuccessParam payParam = new OrderPaySuccessParam();
//订单号
payParam.OrderNO = param.OrderNO;
//交易号
payParam.TradeNO = param.TradeNO;
//支付方式
payParam.PayMethod = PaymentMethodKind.Online;
//卖家收款账户
payParam.Account = config.ApplePayBankAccount;
//卖家收款账户银行
payParam.Bank = config.ApplePayBankName;
//买家账户
payParam.PayAccount = "";
//买家收款账户银行
payParam.PayBank = "";
//实际支付金额
var order = OrderService.Instance.GetList(o => o.OrderNO == param.OrderNO).FirstOrDefault();
//苹果支付没有返回支付金额,为了避免后期验证不通过,设置总金额为实际订单金额
payParam.TotalAmount = order.TotalAmount;
//支付时间
payParam.PayDate = DateTime.Now;
//支付工具类型
payParam.PayType = PayTypeKind.ApplePay;
//记录支付凭证到流水账
payParam.AppleReceipt = param.AppleReceipt;
OrderService.Instance.OrderPaySuccess(payParam);
return true;
}
else
{
return false;
}
}
else
{
throw new Exception("此支付凭证已被使用,请勿重复使用");
}
}
catch
{
return false;
}
}