phonegap(cordova) 自定義插件代碼篇(一)----IAP 應用內支付

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;
            }
        }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章