FastSpring 提供了一款创新的电子商务引擎,旨在克服困扰软件电子商务公司的易用性、客户服务和成本等问题。
FastSpring 的嵌入商店由一个控制器和一些集成点以及 WebKit 的 WebView 组成。它薄而灵活,使您可以根据应用程序的最佳方式集成 FastSpring。
要了解其工作原理,SDK 提供了两个示例和一个测试应用程序。所有源代码均在 MIT 许可下发布。它接受贡献,并且其使用不受限制。请参阅 RELEASE_NOTES.html 了解最新更改。
FsprgEmbeddedStore 主要由 FsprgEmbeddedStoreController
和其代理协议 FsprgEmbeddedStoreDelegate
组成。
FsprgEmbeddedStoreController
控制连接的 WebView
(WebKit)。它提供了加载商店、监控页面加载进度以及测试当前连接是否安全(https)的功能。
@interface FsprgEmbeddedStoreController : NSObject
- (WebView *)webView;
- (void)setWebView:(WebView *)aWebView;
- (id <FsprgEmbeddedStoreDelegate>)delegate;
- (void)setDelegate:(id <FsprgEmbeddedStoreDelegate>)aDelegate;
- (void)loadWithParameters:(FsprgStoreParameters *)parameters;
- (void)loadWithContentsOfFile:(NSString *)aPath;
- (BOOL)isLoading;
- (double)estimatedLoadingProgress;
- (BOOL)isSecure;
- (NSString *)storeHost;
@end
此外,它还定义了由 FsprgEmbeddedStoreDelegate
协议指定的某些集成点。它通知团队初始加载商店、随后的页面加载和订单完成。还可以定义一个视图向用户显示订单确认。
typedef enum {
FsprgPageFS,
FsprgPagePayPal,
FsprgPageUnknown
} FsprgPageType;
@protocol FsprgEmbeddedStoreDelegate <NSObject>
- (void)didLoadStore:(NSURL *)url;
- (void)didLoadPage:(NSURL *)url ofType:(FsprgPageType)pageType;
- (void)didReceiveOrder:(FsprgOrder *)order;
- (NSView *)viewWithFrame:(NSRect)frame forOrder:(FsprgOrder *)order;
- (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame;
- (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame;
@end
使用我们的 CocoaPod 或执行以下步骤。
FsprgEmbeddedStoreMac/FsprgEmbeddedStore
。我们建议取消选中 将项复制到目标组的文件夹中
的选项。FsprgEmbeddedStoreMac/FsprgEmbeddedStore/Tests
的引用。AppController
并使用 FsprgEmbeddedStoreController
。Example1.app 和 Example2.app 展示了如何详细实现 AppController
。AppController
实例。AppController
的storeView出口。@interface AppController : NSObject <FsprgEmbeddedStoreDelegate> {
IBOutlet WebView* storeView;
FsprgEmbeddedStoreController *storeController;
}
- (FsprgEmbeddedStoreController *)storeController;
- (void)setStoreController:(FsprgEmbeddedStoreController *)aStoreController;
- (IBAction)load:(id)sender;
@end
有时用户更喜欢使用Web商店而不是嵌入式商店。使用FsprgStoreParameters
构建Web商店的URL,并通过使用NSWorkspace
在默认浏览器中打开它。
- (IBAction)openWebStoreInBrowser:(id)sender
{
FsprgStoreParameters *parameters = [FsprgStoreParameters parameters];
[parameters setOrderProcessType:kFsprgOrderProcessDetail];
[parameters setStoreId:@"your_store" withProductId:@"your_product"];
[parameters setMode:kFsprgModeTest];
[[NSWorkspace sharedWorkspace] openURL:[parameters toURL]];
}
FsprgOrder对象代表通过FsprgEmbeddedStoreDelegate
协议返回的订单确认。为了避免您深入头文件,以下部分包含真实世界的示例和FsprgOrder及其相关类的简化API文档。
以下是一个真实世界的示例,展示了从已完成的许可证中获取序列号的最常见情况。感谢来自SmileOnMyMac的Greg Scown分享。
- (void)didReceiveOrder:(FsprgOrder *)order
{
NSEnumerator *e = [[order orderItems] objectEnumerator];
FsprgOrderItem *item = nil;
while (item = [e nextObject]) {
if ([[item productName] hasPrefix:@"MyItemNamePrefix"]) {
NSString *userName = [[item license] licenseName];
NSString *serialNumber = [[item license] firstLicenseCode];
if ([[[item productName] lowercaseString] rangeOfString:@"upgrade"].location != NSNotFound) {
NSLog(@"Upgrade purchase:\nName: %@\nSerial #: %@", userName, serialNumber);
} else {
NSLog(@"Full purchase:\nName: %@\nSerial #: %@", userName, serialNumber);
}
}
}
}
- (BOOL)orderIsTest;
- (NSString *)orderReference;
- (NSString *)orderLanguage;
- (NSString *)orderCurrency;
- (NSNumber *)orderTotal;
- (NSNumber *)orderTotalUSD;
- (NSString *)customerFirstName;
- (NSString *)customerLastName;
- (NSString *)customerCompany;
- (NSString *)customerEmail;
- (FsprgOrderItem *)firstOrderItem; // Shortcut for [[self orderItems] objectAtIndex:0].
- (NSArray *)orderItems;
- (NSString *)productName;
- (NSString *)productDisplay;
- (NSNumber *)quantity;
- (NSNumber *)itemTotal;
- (NSNumber *)itemTotalUSD;
- (NSString *)subscriptionReference; // See https://support.fastspring.com/entries/236487-api-subscriptions
- (NSURL *)subscriptionCustomerURL; // This URL can be presented to the customer to manage their subscription.
- (FsprgFulfillment *)fulfillment;
- (FsprgLicense *)license; // Shortcut for [[self fulfillment] valueForKey:@"license"]
- (FsprgFileDownload *)download; // Shortcut for [[self fulfillment] valueForKey:@"download"]
/*!
* @param aKey type of fulfillment (e.g. license, download)
* @result Specific fulfillment information (FsprgLicense, FsprgFileDownload).
*/
- (id)valueForKey:(NSString *)aKey;
- (NSString *)licenseName;
- (NSString *)licenseEmail;
- (NSString *)licenseCompany;
- (NSString *)firstLicenseCode;
- (NSArray *)licenseCodes;
- (NSDictionary *)licensePropertyList;
- (NSURL *)licenseURL;
- (NSURL *)fileURL;
Example1 app通过访问MacOS的AddressBook来设置默认的联系人字段。订单确认是通过Interface Builder内部构建的视图XIB。
init
中将self设置为委托awakeFromNib
中将webView设置为FsprgEmbeddedStoreController
load:
委托给FsprgEmbeddedStoreController
的loadWithParameters:
NSViewController
(在此为OrderViewController
)实现viewWithFrame:forOrder:
,该NSViewController
使用Interface Builder内部定义的视图XIB@implementation AppController
- (id) init
{
self = [super init];
if (self != nil) {
[self setStoreController:[[[FsprgEmbeddedStoreController alloc] init] autorelease]];
[[self storeController] setDelegate:self];
}
return self;
}
- (void)awakeFromNib
{
[[self storeController] setWebView:storeView];
[self load:nil];
}
- (IBAction)load:(id)sender
{
FsprgStoreParameters *parameters = [FsprgStoreParameters parameters];
...
[[self storeController] loadWithParameters:parameters];
}
- (NSView *)viewWithFrame:(NSRect)frame forOrder:(FsprgOrder *)order
{
OrderViewController *orderViewController = [[OrderViewController alloc] initWithNibName:@"OrderView" bundle:nil];
[orderViewController setRepresentedObject:order];
[[orderViewController view] setFrame:frame];
return [orderViewController view];
}
@end
NSViewController
创建类OrderViewController
OrderViewController
FSOrder
),向用户展示订单确认数据Example2使用HTML、CSS和JavaScript展示订单确认。它使用Matt Gemmell的MGTemplateEngine来渲染HTML。
AppController看起来与Example1相同。唯一的区别是viewWithFrame:forOrder:
的实现。它使用WebFrame
的loadHTMLString:baseURL:
方法来加载HTML并将其展示给用户。
@implementation AppController
- (NSView *)viewWithFrame:(NSRect)frame forOrder:(FsprgOrder *)order
{
MGTemplateEngine *engine = [MGTemplateEngine templateEngine];
[engine setMatcher:[ICUTemplateMatcher matcherWithTemplateEngine:engine]];
NSString *templatePath = [[NSBundle mainBundle] pathForResource:@"OrderView" ofType:@"html"];
NSDictionary *variables = [NSDictionary dictionaryWithObject:order forKey:@"order"];
NSString *htmlString = [engine processTemplateInFileAtPath:templatePath withVariables:variables];
NSString *templateDirectory = [templatePath substringToIndex:[templatePath length]-[[templatePath lastPathComponent] length]];
NSURL *baseURL = [NSURL URLWithString:[NSString stringWithFormat:@"file://%@", templateDirectory]];
WebFrame *webFrame = [[[WebView alloc] initWithFrame:frame] mainFrame];
[webFrame loadHTMLString:htmlString baseURL:baseURL];
return [webFrame frameView];
}
@end
由于我们将 FsprgOrder
设置为一个变量,现在我们可以在模板内部方便地访问订单信息。baseURL 指向资源目录。因此,我们可以访问 CSS 文件来美化视图,以及 JavaScript 来添加一些行为和良好效果。
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
<title>Your Order</title>
<link rel="stylesheet" type="text/css" href="OrderView.css">
<script src="jquery-1.4.2.js"></script>
<script language="javascript">
$(function() {
$(".orderItemsTitle").fadeIn(2000);
$(".orderItem").fadeIn(2000);
});
</script>
</head>
<body>
<div class="thankYouNote">Thanks for your order {{ order.customerFirstName }}!</div>
<div class="orderItemsTitle">Ordered items</div>
{% for orderItem in order.orderItems %}
<div class="orderItem">
<div class="productName">
{{ orderItem.productName }}
{% if orderItem.quantity > 1 %} ({{ orderItem.quantity }}) {% /if %}
</div>
<div class="licenseKey">Your license key: {{ orderItem.license.firstLicenseCode }}</div>
</div>
{% /for %}
</body>
</html>
Test 应用程序允许您探索 FastSpring 的参数,并显示原始订单确认结果(XML plist 格式)。
您还可以将确认结果存储为 plist 文件,并使用 FsprgEmbeddedStoreController
的 loadWithContentsOfFile:
方法来加载它。这简化了订单确认视图的开发和测试。