Skip to content
This repository has been archived by the owner on May 24, 2023. It is now read-only.

Commit

Permalink
Merge pull request #48 from trustedshops/feature/APP-384
Browse files Browse the repository at this point in the history
Make email optional
  • Loading branch information
GeroHerkenrath committed Nov 28, 2016
2 parents c7300d4 + feff805 commit de04c9c
Show file tree
Hide file tree
Showing 31 changed files with 255 additions and 224 deletions.
12 changes: 8 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
osx_image: xcode7.3
osx_image: xcode8.1
language: objective-c

cache:
- bundler
- cocoapods

before_install:
- export IOS_SIMULATOR_UDID=`instruments -s devices | grep "iPhone SE (10.1" | awk -F '[ ]' '{print $4}' | awk -F '[\[]' '{print $2}' | sed 's/.$//'`
- echo $IOS_SIMULATOR_UDID
- open -a "simulator" --args -CurrentDeviceUDID $IOS_SIMULATOR_UDID

install:
- bundle install
# - bundle exec pod repo update --silent
- bundle exec pod install --project-directory=Example

script:
- set -o pipefail && xcodebuild test -workspace Example/Trustbadge.xcworkspace -scheme Trustbadge_Example -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6s' -derivedDataPath ${TRAVIS_BUILD_DIR}/myDerivedData ONLY_ACTIVE_ARCH=YES GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c
- set -o pipefail && travis_retry xcodebuild test -workspace Example/Trustbadge.xcworkspace -scheme Trustbadge_Example -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone SE' -derivedDataPath ${TRAVIS_BUILD_DIR}/myDerivedData ONLY_ACTIVE_ARCH=YES GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c
- pod lib lint --quick

after_success: slather coverage -c -s -t --ignore '../*' -b ${TRAVIS_BUILD_DIR}/myDerivedData --verbose
after_success: slather coverage -c -s -t --ignore '../*' -b ${TRAVIS_BUILD_DIR}/myDerivedData --input-format profdata --verbose
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Trustbadge

## Version 0.8.0

* The eMail is now optional for TRSOrder objects (and thus also for TRSCustomer objects). This allows processing orders for which the App does not collect an email address itself (for example in-app purchases). See updated README file.

## Version 0.7.0

* Changed the popup card that is shown when the user clicks on the seal image to the standard trustcard that is also used in web shops. What exactly is shown on that card also depends on what services the shop has booked at Trusted Shops.
Expand Down
4 changes: 2 additions & 2 deletions Example/Tests/TRSOrderSpec.m
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ - (BOOL)areFieldsComplete;
void (^aCallback)(NSError * _Nullable error) = ^void(NSError * _Nullable error) {
expect(error).to.beNil();
expect(helperPointer.nextActionFlag).to.equal(TRSNoNextActions);
expect(helperPointer.insuranceState).to.equal(TRSInsured);
expect(helperPointer.insuranceState).to.equal(TRSInsuranceStateHandledExternally);
expect(helperPointer.orderState & TRSOrderProcessed).to.equal(TRSOrderProcessed);
expect(helperPointer.consumer.membershipStatus).to.equal(TRSMemberKnown);
};
Expand Down Expand Up @@ -324,7 +324,7 @@ - (BOOL)areFieldsComplete;
void (^aCallback)(NSError * _Nullable error) = ^void(NSError * _Nullable error) {
expect(error).to.beNil();
expect(helperPointer.nextActionFlag).to.equal(TRSNoNextActions);
expect(helperPointer.insuranceState).to.equal(TRSUserDeclinedInsurance);
expect(helperPointer.insuranceState).to.equal(TRSInsuranceStateHandledExternally);
expect(helperPointer.orderState & TRSOrderProcessed).to.equal(TRSOrderProcessed);
expect(helperPointer.consumer.membershipStatus).to.equal(TRSMemberKnown);
};
Expand Down
128 changes: 66 additions & 62 deletions Example/Trustbadge/Main.storyboard

Large diffs are not rendered by default.

15 changes: 11 additions & 4 deletions Example/Trustbadge/TRSViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ - (void)viewWillAppear:(BOOL)animated {
- (IBAction)submitTestOrder:(id)sender {
// if we don't have all the needed data, just do nothing
if ( !self.orderNoField.text || [self.orderNoField.text isEqualToString:@""] ||
!self.emailField.text || [self.emailField.text isEqualToString:@""] ||
// !self.emailField.text || [self.emailField.text isEqualToString:@""] ||
!self.amountField.text || [self.amountField.text isEqualToString:@""] ) {
NSLog(@"Input error: some needed fields are empty");
return;
Expand All @@ -79,9 +79,12 @@ - (IBAction)submitTestOrder:(id)sender {
date = [dateFormatter dateFromString:self.estDeliveryDateField.text];
}

NSString *email = self.emailField.text; // this has already been validated by updateUI / dismissKeyboard:
email = !email || [email isEqualToString:@""] ? nil : email;

TRSOrder *anOrder = [[TRSOrder alloc] initWithTrustedShopsID:self.tsIDField.text
apiToken:@"NOT NEEDED AT THE ATM"
email:self.emailField.text
email:email
ordernr:self.orderNoField.text
amount:[NSNumber numberWithDouble:amount]
curr:self.currencyField.text
Expand All @@ -96,7 +99,8 @@ - (IBAction)submitTestOrder:(id)sender {
NSLog(@"%@uccessfully validated anOrder", error ? @"Uns" : @"S");
}];
[anOrder finishWithCompletionBlock:^(NSError * _Nullable error) {
NSLog(@"Finished anOrder, user %@ insurance", anOrder.insuranceState == TRSUserDeclinedInsurance ? @"declined or already has" : @"bought");
NSLog(@"Finished anOrder, user insurance %@",
anOrder.insuranceState == TRSInsuranceStateHandledExternally ? @"handled externally" : @"unknown");
}];
}

Expand Down Expand Up @@ -146,6 +150,9 @@ - (void)updateUI {
}

- (NSString *)validateEmailString:(NSString *)email {
if (!email || [email isEqualToString:@""]) {
return @"";
}
if ([email containsString:@"@"]) { // does it have an @ in it?
NSMutableArray *delimited = [[email componentsSeparatedByString:@"@"] mutableCopy];
if (![[delimited lastObject] containsString:@"."]) { // a delimiter for the toplevel domain?
Expand All @@ -170,7 +177,7 @@ - (NSString *)validateAmountString:(NSString *)amountString {

- (void)checkSubmitButtonState {
if ( !self.orderNoField.text || [self.orderNoField.text isEqualToString:@""] ||
!self.emailField.text || [self.emailField.text isEqualToString:@""] ||
// !self.emailField.text || [self.emailField.text isEqualToString:@""] ||
!self.amountField.text || [self.amountField.text isEqualToString:@""] ) {
self.submitButton.enabled = NO;
} else {
Expand Down
2 changes: 1 addition & 1 deletion Example/Trustbadge/Trustbadge-Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>201611281157</string>
<string>201611281315</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ source "https://rubygems.org"

gem "bundler", "~> 1.13.2"
gem "cocoapods", "~> 1.1.1"
gem "slather", "~> 2.2.1"
gem "slather", "~> 2.3.0"
gem "xcpretty", "~> 0.2.1"
gem "activesupport", "~> 4.2.6"
14 changes: 9 additions & 5 deletions Pod/Classes/Private/TRSCheckoutViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ + (instancetype)checkoutViewController {
}

- (void)loadView { // keep in mind this is only called once for each instance!
self.tappedToCancel = YES; // we assume every close anywhere is a cancel unless explcitly said otherwise
self.tappedToCancel = YES; // we assume every close anywhere is a cancel unless explicitly said otherwise
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
WKUserContentController *ucController = [[WKUserContentController alloc] init];
[ucController addScriptMessageHandler:self name:@"trs_ios_listener"];
Expand Down Expand Up @@ -182,14 +182,18 @@ - (void)resizePopinToSize:(CGSize)newSize {

- (BOOL)constructJavaScriptStringsForOrder:(TRSOrder *)order {
// validation note: actually, the order class already ensures needed values are present
if (!order.consumer.email || !order.ordernr || !order.curr || !order.amount ||
if (!order.ordernr || !order.curr || !order.amount ||
!order.paymentType || !order.tsID) {
return NO;
}

self.jsStrings = [[NSMutableArray alloc] initWithCapacity:8];
[self.jsStrings addObject:[[TRSCheckoutViewController baseJS][@"email"]
stringByReplacingOccurrencesOfString:@"%s" withString:order.consumer.email]];
NSUInteger stringCount = order.consumer.email ? 8 : 7;

self.jsStrings = [[NSMutableArray alloc] initWithCapacity:stringCount];
if (stringCount == 8) {
[self.jsStrings addObject:[[TRSCheckoutViewController baseJS][@"email"]
stringByReplacingOccurrencesOfString:@"%s" withString:order.consumer.email]];
}
[self.jsStrings addObject:[[TRSCheckoutViewController baseJS][@"ordernr"]
stringByReplacingOccurrencesOfString:@"%s" withString:order.ordernr]];
[self.jsStrings addObject:[[TRSCheckoutViewController baseJS][@"curr"]
Expand Down
1 change: 0 additions & 1 deletion Pod/Classes/Private/TRSConsumer+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

@interface TRSConsumer ()

@property (nonatomic, readwrite, copy, nonnull) NSString *email;
@property (nonatomic, readwrite, assign) TRSMembershipStatus membershipStatus;

@end
12 changes: 6 additions & 6 deletions Pod/Classes/Private/TRSShop.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ - (instancetype)initWithDictionary:(NSDictionary *)shopInfo {
return nil;
}

self.trustMark = [[TRSTrustMark alloc] initWithDictionary:shopInfo[@"trustMark"]];
self.languageISO2 = shopInfo[@"languageISO2"] ? shopInfo[@"languageISO2"] : @"en";
self.targetMarketISO3 = shopInfo[@"targetMarketISO3"] ? shopInfo[@"targetMarketISO3"] : @"EUO";
self.tsId = shopInfo[@"tsId"];
self.url = shopInfo[@"url"];
self.name = shopInfo[@"name"];
_trustMark = [[TRSTrustMark alloc] initWithDictionary:shopInfo[@"trustMark"]];
_languageISO2 = shopInfo[@"languageISO2"] ? shopInfo[@"languageISO2"] : @"en";
_targetMarketISO3 = shopInfo[@"targetMarketISO3"] ? shopInfo[@"targetMarketISO3"] : @"EUO";
_tsId = shopInfo[@"tsId"];
_url = shopInfo[@"url"];
_name = shopInfo[@"name"];
}
return self;
}
Expand Down
8 changes: 4 additions & 4 deletions Pod/Classes/Private/TRSSingleStarView.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ - (instancetype)initWithFrame:(CGRect)frame percentFilled:(NSNumber *)percentFil
} else if (percentFilled.doubleValue < 0.0) {
percentFilled = @0;
}
self.percentFilled = percentFilled;
_percentFilled = percentFilled;
[self finishInit];
}
return self;
Expand All @@ -47,10 +47,10 @@ - (instancetype)initWithFrame:(CGRect)frame {
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
self.percentFilled = [coder decodeObjectForKey:kTRSSingleStarViewPercentFilledKey];
_percentFilled = [coder decodeObjectForKey:kTRSSingleStarViewPercentFilledKey];
[self finishInit];
self.activeStarColor = [coder decodeObjectForKey:kTRSSingleStarViewActiveStarColorKey];
self.inactiveStarColor = [coder decodeObjectForKey:kTRSSingleStarViewInactiveStarColorKey];
_activeStarColor = [coder decodeObjectForKey:kTRSSingleStarViewActiveStarColorKey];
_inactiveStarColor = [coder decodeObjectForKey:kTRSSingleStarViewInactiveStarColorKey];
}
return self;
}
Expand Down
6 changes: 3 additions & 3 deletions Pod/Classes/Private/TRSTrustMark.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ - (instancetype)init
- (instancetype)initWithDictionary:(NSDictionary *)trustMarkInfo {
self = [super init];
if (self) {
self.status = trustMarkInfo[@"status"] ? trustMarkInfo[@"status"] : @"INVALID"; // TODO: check possible values
_status = trustMarkInfo[@"status"] ? trustMarkInfo[@"status"] : @"INVALID"; // TODO: check possible values
NSDateFormatter *dateFormatter = [NSDateFormatter new];
dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ";
if (trustMarkInfo[@"validFrom"]) {
self.validFrom = [dateFormatter dateFromString:trustMarkInfo[@"validFrom"]];
_validFrom = [dateFormatter dateFromString:trustMarkInfo[@"validFrom"]];
}
if (trustMarkInfo[@"validTo"]) {
self.validTo = [dateFormatter dateFromString:trustMarkInfo[@"validTo"]];
_validTo = [dateFormatter dateFromString:trustMarkInfo[@"validTo"]];
}
}
return self;
Expand Down
2 changes: 1 addition & 1 deletion Pod/Classes/Private/TRSTrustbadge.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ - (instancetype)initWithData:(NSData *)data {
return nil;
}

self.shop = [[TRSShop alloc] initWithDictionary:json[@"response"][@"data"][@"shop"]];
_shop = [[TRSShop alloc] initWithDictionary:json[@"response"][@"data"][@"shop"]];
return self;
}

Expand Down
8 changes: 4 additions & 4 deletions Pod/Classes/Public/TRSConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ typedef NS_ENUM(NSUInteger, TRSMembershipStatus) {
You can create your own `TRSConsumer` objects, but currently there is no way for you to change its
`TRSMembershipStatus` outside of the purchase process.
@param email The email address of the consumer. Must not be `nil`.
@param email The email address of the consumer.
@see [TRSOrder initWithTrustedShopsID:apiToken:email:ordernr:amount:curr:paymentType:deliveryDate:]
*/
- (nullable instancetype)initWithEmail:(nonnull NSString *)email NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithEmail:(nullable NSString *)email NS_DESIGNATED_INITIALIZER;

/**
The email address of the consumer.
During the purchase process, we use it to identify the consumer in our database. Set on initialiation, can't be `nil`.
During the purchase process, we use it to identify the consumer in our database. Set on initialiation.
*/
@property (nonatomic, readonly, nonnull) NSString *email;
@property (nonatomic, copy, nullable) NSString *email;
/**
The membership status the consumer has at Trusted Shops.
Expand Down
6 changes: 3 additions & 3 deletions Pod/Classes/Public/TRSConsumer.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ - (instancetype)init
- (instancetype)initWithEmail:(NSString *)email {
self = [super init];
if (self) {
if (![self isValidEmail:email]) {
if (email && ![self isValidEmail:email]) {
return nil;
}
self.email = email;
self.membershipStatus = TRSMemberUnverified;
_email = email;
_membershipStatus = TRSMemberUnverified;
}
return self;
}
Expand Down
8 changes: 4 additions & 4 deletions Pod/Classes/Public/TRSCriteria.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ - (instancetype)initWithMark:(NSNumber *)mark type:(TRSCriteriaType)type {
self = [super init];
if (self) {
if ([mark floatValue] > 5.0f) {
self.mark = @5;
_mark = @5;
} else if ([mark floatValue] < 1.0f) {
self.mark = @1;
_mark = @1;
} else {
self.mark = mark;
_mark = mark;
}
self.type = type;
_type = type;
}
return self;
}
Expand Down
24 changes: 17 additions & 7 deletions Pod/Classes/Public/TRSOrder.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ typedef NS_ENUM(NSUInteger, TRSInsuranceState) {
/** The order is fully insured. Currently not used. */
TRSFullyInsured,
/** The user declined insuring the order */
TRSUserDeclinedInsurance
TRSUserDeclinedInsurance,
/** The state of the insurance was handled externally, usually in the browser. The SDK itself has no information
whether the user accepted or not. */
TRSInsuranceStateHandledExternally
};

/**
Expand Down Expand Up @@ -93,6 +96,11 @@ typedef NS_ENUM(NSUInteger, TRSNextActionFlag) {
a member at Trusted Shops.
Since this requires user interaction, the calls to do so will open a lightbox in the UI and display the needed
information for the user & process necessary interaction in a webview.
An exception to this behavior is when the provided information is incomplete. Then a more elaborate interaction is
required, so the app switches to mobile Safari & displays a regular webpage for the user to enter missing and/or
additional information. An example for this would be if you cannot provide an email address.
Another case would be if the given currency doesn't match the settings of your account at Trusted Shops (so you
should provide the correct currency that matches your shop/MyTS account).
*/
@interface TRSOrder : NSObject

Expand Down Expand Up @@ -187,11 +195,11 @@ typedef NS_ENUM(NSUInteger, TRSNextActionFlag) {
/**
The designated initializer.
All method arguments except the delivery date are mandatory, otherwise the method returns nil.
All method arguments except email and the delivery date are mandatory, otherwise the method returns nil.
@param trustedShopsID Your Trusted Shops ID.
@param apiToken The token to authenticate your app for the (remote) API at Trusted Shops. Currently can be any `NSString`.
@param email The email your customer used to make the purchase.
@param email The email your customer used to make the purchase. Specify `nil` if you don't have it.
@param orderNo A string uniquely representing the order that was made.
@param amount The actual value of the purchase. Typically a float or double greater than 0 and with 2 digits after the decimal point.
@param currency A string denoting the purchase the transaction was made in, e.g. `@"EUR"`.
Expand All @@ -203,7 +211,7 @@ typedef NS_ENUM(NSUInteger, TRSNextActionFlag) {
*/
- (nullable instancetype)initWithTrustedShopsID:(nonnull NSString *)trustedShopsID
apiToken:(nonnull NSString *)apiToken
email:(nonnull NSString *)email
email:(nullable NSString *)email
ordernr:(nonnull NSString *)orderNo
amount:(nonnull NSNumber *)amount
curr:(nonnull NSString *)currency
Expand All @@ -216,11 +224,11 @@ typedef NS_ENUM(NSUInteger, TRSNextActionFlag) {
A convenience method for creating a `TRSOrder` object.
This method calls the designated initializer.
All method arguments except the delivery date are mandatory, otherwise the method returns nil.
All method arguments except email and the delivery date are mandatory, otherwise the method returns nil.
@param trustedShopsID Your Trusted Shops ID.
@param apiToken The token to authenticate your app for the (remote) API at Trusted Shops. Currently can be any `NSString`.
@param email The email your customer used to make the purchase.
@param email The email your customer used to make the purchase. Specify `nil` if you don't have it.
@param orderNo A string uniquely representing the order that was made.
@param amount The actual value of the purchase. Typically a float or double greater than 0 and with 2 digits after the decimal point.
@param currency A string denoting the purchase the transaction was made in, e.g. `@"EUR"`.
Expand All @@ -232,7 +240,7 @@ typedef NS_ENUM(NSUInteger, TRSNextActionFlag) {
*/
+ (nullable instancetype)TRSOrderWithTrustedShopsID:(nonnull NSString *)trustedShopsID
apiToken:(nonnull NSString *)apiToken
email:(nonnull NSString *)email
email:(nullable NSString *)email
ordernr:(nonnull NSString *)orderNo
amount:(nonnull NSNumber *)amount
curr:(nonnull NSString *)currency
Expand Down Expand Up @@ -264,6 +272,8 @@ typedef NS_ENUM(NSUInteger, TRSNextActionFlag) {
to be shown to the user, informing them about their status at Trusted Shops, the guarantee, etc.
After the user has finished interacting with that dialog the onCompletion block will be called with
`nil` as its `error` parameter.
If the provided information is incomplete (e.g. no email is specified), the app switches to mobile Safari
instead and displays a more elaborate page there for the user to provide missing information.
@param onCompletion A block that is called after the object has been sent to the Trusted Shops API.
Its `error` parameter will be nil unless an error occured.
@see validateWithCompletionBlock:
Expand Down
Loading

0 comments on commit de04c9c

Please sign in to comment.