Commit 6e912e14 by Rune Madsen

Merge pull request #93 from Shopify/runmad.checkout-attributes

Checkout attributes
parents 0f998783 01e6d0c7
......@@ -125,6 +125,37 @@
XCTAssertEqualObjects(_checkout.billingAddress.address1, @"150 Elgin Street");
}
- (void)testCheckoutAttributesAndNotes
{
[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest * _Nonnull request) {
return [self shouldUseMocks];
} withStubResponse:^OHHTTPStubsResponse * _Nonnull(NSURLRequest * _Nonnull request) {
return [OHHTTPStubsResponse responseWithKey:@"testCheckoutFlowUsingCreditCard_1"];
}];
_checkout = [[BUYCheckout alloc] initWithCart:_cart];
NSString *note = @"Order note";
_checkout.note = note;
NSArray *attributes = @[ [[BUYCheckoutAttribute alloc] initWithDictionary:@{ @"name" : @"attribute1", @"value" : @"value1" }], [[BUYCheckoutAttribute alloc] initWithDictionary:@{ @"name" : @"attribute2", @"value" : @"value2" }] ];
_checkout.attributes = attributes;
XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)];
[self.client createCheckout:_checkout completion:^(BUYCheckout *returnedCheckout, NSError *error) {
XCTAssertNil(error);
XCTAssertNotNil(returnedCheckout);
XCTAssertEqualObjects(returnedCheckout.note, note);
XCTAssertEqualObjects(returnedCheckout.attributes, attributes);
_checkout = returnedCheckout;
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:10 handler:^(NSError *error) {
XCTAssertNil(error);
}];
}
- (void)fetchShippingRates
{
......
......@@ -125,7 +125,7 @@
"message": "OK"
},
"testCheckoutFlowUsingCreditCard_1": {
"body": "{\"checkout\":{\"created_at\":\"2015-10-08T13:34:30-04:00\",\"currency\":\"CAD\",\"customer_id\":null,\"email\":\"test@test.com\",\"location_id\":null,\"order_id\":null,\"requires_shipping\":true,\"reservation_time\":300,\"source_name\":\"mobile_app\",\"source_identifier\":\"26915715\",\"source_url\":null,\"taxes_included\":false,\"token\":\"89978073d2d3602c114fbd59becc5f96\",\"updated_at\":\"2015-10-08T13:34:30-04:00\",\"payment_due\":\"2230.99\",\"payment_url\":\"https:\\/\\/us-east-1-deposit.cs.shopify.com\\/sessions\",\"reservation_time_left\":300,\"subtotal_price\":\"2230.99\",\"total_price\":\"2230.99\",\"total_tax\":\"0.00\",\"order\":null,\"order_status_url\":null,\"privacy_policy_url\":null,\"refund_policy_url\":null,\"terms_of_service_url\":null,\"user_id\":null,\"web_url\":\"https:\\/\\/checkout.shopify.com\\/9575792\\/checkouts\\/89978073d2d3602c114fbd59becc5f96\",\"tax_lines\":[],\"line_items\":[{\"id\":\"fbc0aac1cac96369\",\"product_id\":2096063363,\"variant_id\":6030700419,\"sku\":\"\",\"vendor\":\"McCullough Group\",\"title\":\"Actinian Fur Hat\",\"variant_title\":\"Teal\",\"taxable\":false,\"requires_shipping\":true,\"price\":\"2230.99\",\"compare_at_price\":null,\"line_price\":\"2230.99\",\"properties\":{\"size\":\"large\",\"color\":\"red\"},\"quantity\":1,\"grams\":4000,\"fulfillment_service\":\"manual\"}],\"gift_cards\":[],\"shipping_rate\":null,\"shipping_address\":{\"first_name\":\"MobileBuy\",\"last_name\":\"TestBot\",\"phone\":\"1-555-555-5555\",\"company\":\"Shopify Inc.\",\"address1\":\"150 Elgin Street\",\"address2\":\"8th Floor\",\"city\":\"Ottawa\",\"province\":\"Ontario\",\"province_code\":\"ON\",\"country\":\"Canada\",\"country_code\":\"CA\",\"zip\":\"K1N5T5\"},\"credit_card\":null,\"billing_address\":{\"first_name\":\"MobileBuy\",\"last_name\":\"TestBot\",\"phone\":\"1-555-555-5555\",\"company\":\"Shopify Inc.\",\"address1\":\"150 Elgin Street\",\"address2\":\"8th Floor\",\"city\":\"Ottawa\",\"province\":\"Ontario\",\"province_code\":\"ON\",\"country\":\"Canada\",\"country_code\":\"CA\",\"zip\":\"K1N5T5\"},\"discount\":null}}",
"body": "{\"checkout\":{\"created_at\":\"2015-10-08T13:34:30-04:00\",\"currency\":\"CAD\",\"customer_id\":null,\"email\":\"test@test.com\",\"location_id\":null,\"order_id\":null,\"requires_shipping\":true,\"reservation_time\":300,\"source_name\":\"mobile_app\",\"source_identifier\":\"26915715\",\"source_url\":null,\"taxes_included\":false,\"token\":\"89978073d2d3602c114fbd59becc5f96\",\"updated_at\":\"2015-10-08T13:34:30-04:00\",\"payment_due\":\"2230.99\",\"payment_url\":\"https:\\/\\/us-east-1-deposit.cs.shopify.com\\/sessions\",\"reservation_time_left\":300,\"subtotal_price\":\"2230.99\",\"total_price\":\"2230.99\",\"total_tax\":\"0.00\",\"order\":null,\"order_status_url\":null,\"privacy_policy_url\":null,\"refund_policy_url\":null,\"terms_of_service_url\":null,\"user_id\":null,\"web_url\":\"https:\\/\\/checkout.shopify.com\\/9575792\\/checkouts\\/89978073d2d3602c114fbd59becc5f96\",\"tax_lines\":[],\"line_items\":[{\"id\":\"fbc0aac1cac96369\",\"product_id\":2096063363,\"variant_id\":6030700419,\"sku\":\"\",\"vendor\":\"McCullough Group\",\"title\":\"Actinian Fur Hat\",\"variant_title\":\"Teal\",\"taxable\":false,\"requires_shipping\":true,\"price\":\"2230.99\",\"compare_at_price\":null,\"line_price\":\"2230.99\",\"properties\":{\"size\":\"large\",\"color\":\"red\"},\"quantity\":1,\"grams\":4000,\"fulfillment_service\":\"manual\"}],\"gift_cards\":[],\"shipping_rate\":null,\"shipping_address\":{\"first_name\":\"MobileBuy\",\"last_name\":\"TestBot\",\"phone\":\"1-555-555-5555\",\"company\":\"Shopify Inc.\",\"address1\":\"150 Elgin Street\",\"address2\":\"8th Floor\",\"city\":\"Ottawa\",\"province\":\"Ontario\",\"province_code\":\"ON\",\"country\":\"Canada\",\"country_code\":\"CA\",\"zip\":\"K1N5T5\"},\"credit_card\":null,\"billing_address\":{\"first_name\":\"MobileBuy\",\"last_name\":\"TestBot\",\"phone\":\"1-555-555-5555\",\"company\":\"Shopify Inc.\",\"address1\":\"150 Elgin Street\",\"address2\":\"8th Floor\",\"city\":\"Ottawa\",\"province\":\"Ontario\",\"province_code\":\"ON\",\"country\":\"Canada\",\"country_code\":\"CA\",\"zip\":\"K1N5T5\"},\"discount\":null,\"note\":\"Order note\",\"attributes\":{\"attribute1\":\"value1\",\"attribute2\":\"value2\"}}}",
"code": 201,
"message": "Created"
},
......
......@@ -178,6 +178,10 @@
901931691BC5B9BC00D1134E /* BUYProduct.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AF52A7C1A700B0A0087DB2C /* BUYProduct.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019316A1BC5B9BC00D1134E /* BUYSerializable.h in Headers */ = {isa = PBXBuildFile; fileRef = F76CFF1E19CB7C500079C703 /* BUYSerializable.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019316B1BC5B9BC00D1134E /* BUYProductVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AF52A811A700B0A0087DB2C /* BUYProductVariant.h */; settings = {ATTRIBUTES = (Public, ); }; };
9032F2DA1BE9457A00BB9EEF /* BUYCheckoutAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 9032F2D81BE9457A00BB9EEF /* BUYCheckoutAttribute.h */; settings = {ATTRIBUTES = (Public, ); }; };
9032F2DB1BE9457A00BB9EEF /* BUYCheckoutAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 9032F2D81BE9457A00BB9EEF /* BUYCheckoutAttribute.h */; settings = {ATTRIBUTES = (Public, ); }; };
9032F2DC1BE9457A00BB9EEF /* BUYCheckoutAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = 9032F2D91BE9457A00BB9EEF /* BUYCheckoutAttribute.m */; };
9032F2DD1BE9457A00BB9EEF /* BUYCheckoutAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = 9032F2D91BE9457A00BB9EEF /* BUYCheckoutAttribute.m */; };
903BCC7C1B7D1C2D00C21FEB /* BUYProductViewErrorView.h in Headers */ = {isa = PBXBuildFile; fileRef = 903BCC7A1B7D1C2D00C21FEB /* BUYProductViewErrorView.h */; };
903BCC7D1B7D1C2D00C21FEB /* BUYProductViewErrorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 903BCC7B1B7D1C2D00C21FEB /* BUYProductViewErrorView.m */; };
904606AF1B6BC8D700754173 /* BUYProductImageCollectionViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 904606AD1B6BC8D700754173 /* BUYProductImageCollectionViewCell.h */; };
......@@ -328,11 +332,11 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
90DAEC341BC6E50B007555A5 /* PBXContainerItemProxy */ = {
9032F2D61BE93F3D00BB9EEF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F773741519C770CB0039681C /* Project object */;
proxyType = 1;
remoteGlobalIDString = BE9A64271B503C2F0033E558;
remoteGlobalIDString = 901930E11BC5B9BC00D1134E;
remoteInfo = Buy;
};
90E78A4C1BD58F0C005D16C3 /* PBXContainerItemProxy */ = {
......@@ -378,6 +382,8 @@
901335451C187E0400410ED0 /* NSURLComponents+BUYAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURLComponents+BUYAdditions.m"; sourceTree = "<group>"; };
901931701BC5B9BC00D1134E /* Buy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Buy.framework; sourceTree = BUILT_PRODUCTS_DIR; };
901931761BC5BC9100D1134E /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
9032F2D81BE9457A00BB9EEF /* BUYCheckoutAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYCheckoutAttribute.h; sourceTree = "<group>"; };
9032F2D91BE9457A00BB9EEF /* BUYCheckoutAttribute.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYCheckoutAttribute.m; sourceTree = "<group>"; };
903BCC7A1B7D1C2D00C21FEB /* BUYProductViewErrorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BUYProductViewErrorView.h; path = "Product View/BUYProductViewErrorView.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
903BCC7B1B7D1C2D00C21FEB /* BUYProductViewErrorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYProductViewErrorView.m; path = "Product View/BUYProductViewErrorView.m"; sourceTree = "<group>"; };
904606AD1B6BC8D700754173 /* BUYProductImageCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BUYProductImageCollectionViewCell.h; path = "Product View/BUYProductImageCollectionViewCell.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
......@@ -761,6 +767,8 @@
BEB74A1B1B5490140005A300 /* BUYCheckout_Private.h */,
F773749419C77C260039681C /* BUYCheckout.h */,
F773749519C77C260039681C /* BUYCheckout.m */,
9032F2D81BE9457A00BB9EEF /* BUYCheckoutAttribute.h */,
9032F2D91BE9457A00BB9EEF /* BUYCheckoutAttribute.m */,
BEB74A8E1B55A3D00005A300 /* BUYCollection.h */,
9089CC5D1BB48D06009726D6 /* BUYCollection.m */,
900396F41B69563400226B73 /* BUYCollection+Additions.h */,
......@@ -941,6 +949,7 @@
9019315B1BC5B9BC00D1134E /* BUYImageKit.h in Headers */,
9019315C1BC5B9BC00D1134E /* BUYCollection+Additions.h in Headers */,
9019315D1BC5B9BC00D1134E /* NSDateFormatter+BUYAdditions.h in Headers */,
9032F2DB1BE9457A00BB9EEF /* BUYCheckoutAttribute.h in Headers */,
9019315E1BC5B9BC00D1134E /* BUYError.h in Headers */,
9019315F1BC5B9BC00D1134E /* BUYProductHeaderCell.h in Headers */,
901931601BC5B9BC00D1134E /* BUYProductViewErrorView.h in Headers */,
......@@ -1017,6 +1026,7 @@
900E7C841B5DA553006F3C81 /* BUYImageKit.h in Headers */,
900396F61B69563400226B73 /* BUYCollection+Additions.h in Headers */,
90A446251B5EC03F009602AA /* NSDateFormatter+BUYAdditions.h in Headers */,
9032F2DA1BE9457A00BB9EEF /* BUYCheckoutAttribute.h in Headers */,
BE47340F1B66C4EF00AA721A /* BUYError.h in Headers */,
BEB74A6D1B5564200005A300 /* BUYProductHeaderCell.h in Headers */,
903BCC7C1B7D1C2D00C21FEB /* BUYProductViewErrorView.h in Headers */,
......@@ -1065,7 +1075,7 @@
buildRules = (
);
dependencies = (
90DAEC351BC6E50B007555A5 /* PBXTargetDependency */,
9032F2D71BE93F3D00BB9EEF /* PBXTargetDependency */,
);
name = "Mobile Buy SDK Tests";
productName = "Mobile Buy SDK Tests";
......@@ -1244,6 +1254,7 @@
9019310E1BC5B9BC00D1134E /* BUYProduct.m in Sources */,
9019310F1BC5B9BC00D1134E /* BUYImageView.m in Sources */,
901931101BC5B9BC00D1134E /* BUYProductHeaderCell.m in Sources */,
9032F2DD1BE9457A00BB9EEF /* BUYCheckoutAttribute.m in Sources */,
901931111BC5B9BC00D1134E /* BUYCartLineItem.m in Sources */,
901931121BC5B9BC00D1134E /* BUYMaskedCreditCard.m in Sources */,
901931131BC5B9BC00D1134E /* BUYCheckout.m in Sources */,
......@@ -1339,6 +1350,7 @@
BE9A64621B503CF40033E558 /* BUYProduct.m in Sources */,
BEB74A781B55646F0005A300 /* BUYImageView.m in Sources */,
BEB74A6E1B5564230005A300 /* BUYProductHeaderCell.m in Sources */,
9032F2DC1BE9457A00BB9EEF /* BUYCheckoutAttribute.m in Sources */,
9003969C1B601DF400226B73 /* BUYCartLineItem.m in Sources */,
BE5DC3641B71022D00B2BC1E /* BUYMaskedCreditCard.m in Sources */,
BE9A644C1B503C9F0033E558 /* BUYCheckout.m in Sources */,
......@@ -1365,10 +1377,10 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
90DAEC351BC6E50B007555A5 /* PBXTargetDependency */ = {
9032F2D71BE93F3D00BB9EEF /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = BE9A64271B503C2F0033E558 /* Buy Static */;
targetProxy = 90DAEC341BC6E50B007555A5 /* PBXContainerItemProxy */;
target = 901930E11BC5B9BC00D1134E /* Buy */;
targetProxy = 9032F2D61BE93F3D00BB9EEF /* PBXContainerItemProxy */;
};
90E78A4D1BD58F0C005D16C3 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
......
......@@ -35,6 +35,7 @@ FOUNDATION_EXPORT const unsigned char BuyVersionString[];
#import <Buy/BUYAddress.h>
#import <Buy/BUYCart.h>
#import <Buy/BUYCheckout.h>
#import <Buy/BUYCheckoutAttribute.h>
#import <Buy/BUYCreditCard.h>
#import <Buy/BUYDiscount.h>
#import <Buy/BUYGiftCard.h>
......
......@@ -37,6 +37,7 @@
@class BUYTaxLine;
@class BUYLineItem;
@class BUYGiftCard;
@class BUYCheckoutAttribute;
/**
* The checkout object. This is the main object that you will interact with when creating orders on Shopify.
......@@ -244,6 +245,11 @@
@property (nonatomic, copy) NSString *note;
/**
* Extra information that is added to the order
*/
@property (nonatomic, copy) NSArray <BUYCheckoutAttribute *> *attributes;
/**
* The BUYOrder for a completed checkout
*/
@property (nonatomic, strong, readonly) BUYOrder *order;
......
......@@ -42,6 +42,7 @@
#import "NSDateFormatter+BUYAdditions.h"
#import "NSURL+BUYAdditions.h"
#import "NSDictionary+Additions.h"
#import "BUYCheckoutAttribute.h"
@implementation BUYCheckout
......@@ -146,6 +147,7 @@
self.creditCard = [BUYMaskedCreditCard convertObject:dictionary[@"credit_card"]];
self.customerId = [dictionary buy_objectForKey:@"customer_id"];
self.note = dictionary[@"note"];
self.attributes = [BUYCheckoutAttribute convertJSONArray:dictionary[@"attributes"]];
self.privacyPolicyURL = [NSURL buy_urlWithString:dictionary[@"privacy_policy_url"]];
self.refundPolicyURL = [NSURL buy_urlWithString:dictionary[@"refund_policy_url"]];
......@@ -181,13 +183,22 @@
- (NSDictionary *)jsonDictionaryForCheckout
{
//We only need the dirty properties
// We only need the dirty properties
NSSet *dirtyProperties = [self dirtyProperties];
NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
for (NSString *dirtyProperty in dirtyProperties) {
id value = [self jsonValueForValue:[self valueForKey:dirtyProperty]];
json[[BUYCheckout jsonKeyForProperty:dirtyProperty]] = value ?: [NSNull null];
}
// We need to serialize the attributes as they need to be posted as a dictionary
if (json[@"attributes"]) {
NSMutableDictionary *attributeDictionary = [[NSMutableDictionary alloc] init];
for (NSDictionary *attribute in json[@"attributes"]) {
attributeDictionary[[attribute allKeys][0]] = [attribute allValues][0];
}
json[@"attributes"] = attributeDictionary;
}
return @{ @"checkout" : json };
}
......
//
// BUYCheckoutAttribute.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2016 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYObject.h"
#import "BUYSerializable.h"
/**
* A BUYCheckoutAttribute represents a checkout attributes key and value
*/
@interface BUYCheckoutAttribute : BUYObject <BUYSerializable>
/**
* The attribute name
*/
@property (nonatomic, strong, nonnull) NSString *name;
/**
* The attribute value
*/
@property (nonatomic, strong, nonnull) NSString *value;
@end
//
// BUYCheckoutAttribute.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2016 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYCheckoutAttribute.h"
@implementation BUYCheckoutAttribute
- (void)updateWithDictionary:(NSDictionary *)dictionary
{
self.name = dictionary[@"name"];
self.value = dictionary[@"value"];
}
- (NSDictionary *)jsonDictionaryForCheckout
{
return @{ self.name : self.value };
}
- (BOOL)isEqual:(id)object
{
BOOL same = NO;
if (self == object) {
same = YES;
} else if ([object isKindOfClass:self.class]) {
BUYCheckoutAttribute *attribute = (BUYCheckoutAttribute *)object;
same = ([self.name isEqualToString:attribute.name] && [self.value isEqualToString:attribute.value]);
}
return same;
}
- (NSUInteger)hash
{
return [self.name hash] ^ [self.value hash];
}
@end
......@@ -34,6 +34,7 @@
#import "BUYCart.h"
#import "BUYCartLineItem.h"
#import "BUYCheckout.h"
#import "BUYCheckoutAttribute.h"
#import "BUYClient+Test.h"
#import "BUYClient.h"
#import "BUYCollection.h"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment