3

我在我的应用程序中使用cyberSource 集成Apple Pay 集成。我这样做是为了什么。
1- 我已经创建了商家 ID 2- 我已经在http://www.cybersource.com/
上创建了测试帐户 3- 我已经下载了适用于 iOS 的网络资源 SDK。 4-我已经设法运行使用 SDK 下载的演示应用程序。 5-当我运行演示应用程序时,我收到了这个错误。


"Transaction Details .Accepted: No .Auth Amount: (null) Error: Unknown error"   

我已正确提供我的商家帐户。还有其他字段,我不确定如何获取这些值

static NSString* kMetadataEncodedValue = @"RklEPUNPTU1PTi5MRy5JTkFQUC5QQVlNRU5U";
static NSString* const kPaymentSolutionDefaultValue = @"001";

static NSString* const kEnvTest = @"test";
static NSString* const kEnvLive = @"live";

static NSString* const kKeyMerchantID = @"merchant_otm_eyebuy_acct";
static NSString* const kKeyMerchantExternalID = @"merchant_otm_eyebuy_acct";
static NSString* const kKeyTransactionKey = @"transactionKey";
static NSString* const kKeyEncryptedBlob = @"encryptedBlob";
static NSString* const kKeyEnv = @"env";

- (IBAction)payButtonTouchDown:(id)sender {
    [self.amountTextField resignFirstResponder];

    NSString* requestType = [self.requestTypeSelection titleForSegmentAtIndex:self.requestTypeSelection.selectedSegmentIndex];
    [self updateStatusMessage:[NSString stringWithFormat:@"Submitting %@ request...", requestType]];
    self.payButton.enabled = NO;

    NSString *amountText = self.amountTextField.text;
    NSDecimalNumber *amountValue = [NSDecimalNumber decimalNumberWithString:amountText];

    BOOL isDecimal = amountValue!= nil;
    if (isDecimal) {
        // TODO: Pass in encrypted payment data from PassKit
        [self performRequestWithEncryptedPaymentData:self.selectedAccountData[kKeyEncryptedBlob] withPaymentAmount:amountValue];

    }
    else {
        self.payButton.enabled = YES;
        self.statusText.text = @"Enter valid Amount";
    }

}

- (IBAction)requestTypeSelectionValueChanged:(UISegmentedControl *)sender {
    [self updateRequestSelection];
}

-(void) updateRequestSelection {
    NSString* requestType = [self.requestTypeSelection titleForSegmentAtIndex:self.requestTypeSelection.selectedSegmentIndex];
    [self updateStatusMessage:[NSString stringWithFormat:@"Tap '%@' to %@ request.", self.payButton.currentTitle, requestType]];
}

- (void) updateStatusMessage: (NSString*) message
{
    self.statusText.text = message;
    self.payButton.enabled = YES;
}

- (void)performRequestWithEncryptedPaymentData: (NSString*) encryptedPaymentData withPaymentAmount: (NSDecimalNumber*) paymentAmount
{
    VMposItem *item = [[VMposItem alloc] init];
    item.name = NSLocalizedString(@"Item no 1", nil);
    item.price = paymentAmount;
    VMposTransactionObject *transactionObject = [VMposTransactionObject createTransaction:VMPOS_TRANSACTION_PAYMENT];

    [transactionObject addItem:item];
    [transactionObject calculateTotals];

    // TODO: Encrypted Payment is created by client application based
    // on specification from SOAP API. The following values are just place holders
    VMposEncryptedPayment* payment = [VMposEncryptedPayment new];
    payment.encodedData = encryptedPaymentData;
    payment.encodedMetadata = kMetadataEncodedValue;
    payment.paymentSolution = kPaymentSolutionDefaultValue;

    // Purchase details
    VMposPurchaseDetails* purchaseDetails = [VMposPurchaseDetails new];
    purchaseDetails.partialIndicator = NO;

    // Sample Billing information
    VMposAddress* billTo = [VMposAddress new];
    billTo.firstName = @"John";
    billTo.lastName = @"Doe";
    billTo.email = @"john.doe@yahoo.com";
    billTo.street1 = @"1234 Pine St.";
    billTo.city = @"Redmond";
    billTo.state = @"WA";
    billTo.postalCode = @"98052";
    billTo.country = @"US";

    // Save transaction information
    transactionObject.encryptedPayment = payment;
    transactionObject.purchaseDetails = purchaseDetails;
    transactionObject.purchaseDetails.commerceIndicator = @"internet";
    transactionObject.transactionCode = @"ref_code_12345678";
    transactionObject.billTo = billTo;

    // Build fingerprint
    //--WARNING!----------------
    // Finger print generation requires the transaction key. This should
    // be done at the server. It is shown here only for Demo purposes.
    NSString* merchantID = self.selectedAccountData[kKeyMerchantID];
    NSString* fingerprint = [self buildFingerprintWithTransaction:transactionObject withMerchantId:merchantID];
    NSLog(@"Fingerprint: %@", fingerprint);

    VMposGateway* gateway = [VMposGateway sharedInstance];
    [gateway initSessionWithUserName:merchantID withMerchantId:merchantID withFingerprint: fingerprint withDelegate:self];


    if (self.selectedAccountData[kKeyEnv] == kEnvLive) {
        [VMposSettings sharedInstance].cybsEnvironment = ENV_LIVE;
    }
    else
    {
        [VMposSettings sharedInstance].cybsEnvironment = ENV_TEST;
    }

    if (self.requestTypeSelection.selectedSegmentIndex == 0)
    {
        [gateway performAuthorizationWithTransaction:transactionObject withDelegate:self];
    }
    else
    {
        [gateway performSaleWithTransaction:transactionObject withDelegate:self];
    }
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self configureAccounts];

    [self updateStatusMessage:[NSString stringWithFormat:@"Tap '%@' to submit a test request.", self.payButton.currentTitle]];
    self.amountTextField.keyboardType = UIKeyboardTypeDecimalPad;
    self.amountTextField.text = @"1.09";
    [self.requestTypeSelection setSelectedSegmentIndex:0];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
    return 1;
}

// returns the # of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    return self.configuredAccounts.count;
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    NSDictionary* rowData = self.configuredAccounts[row];
    return [NSString stringWithFormat:@"%@ (%@)", rowData[kKeyMerchantID], rowData[kKeyEnv]];
}

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
    self.selectedAccountData = self.configuredAccounts[row];
}

//! Callback for user session initialization
- (void) didInitUserSession: (VMposUserSession*) paramUserSession withError:(VMposError*)paramError {

}

//! provides feedback from finished authorization transaction request
/*!
 \param paramResponseData gateway data retrieved from server (contains information about transaction status)
 \param paramError an error if request failed
 */
- (void) authorizationFinishedWithGatewayResponse:(VMposGatewayResponse *)paramResponseData
                                        withError:(VMposError *)paramError {
    self.authorized = YES;
    [self updateStatusMessageWithResponse: (VMposGatewayResponse *)paramResponseData withError: paramError];
}

//! provides feedback from finished sale request
/*!
 \param paramResponseData gateway data retrieved from server (contains information about transaction status)
 \param paramError an error if request failed
 */
- (void) saleFinishedWithGatewayResponse:(VMposGatewayResponse *)paramResponseData
                               withError:(VMposError *)paramError
{

    self.authorized = YES;
    [self updateStatusMessageWithResponse: (VMposGatewayResponse *)paramResponseData withError: paramError];
}

- (void) updateStatusMessageWithResponse: (VMposGatewayResponse *)paramResponseData withError: (NSError*) paramError
{
    NSMutableString* s = [NSMutableString new];

    if (paramResponseData)
    {
        [s appendString: @"\nTransaction Details:"];
        [s appendFormat: @"\n  * Accepted: %@", paramResponseData.isAccepted ? @"Yes" : @"No"];
        [s appendFormat: @"\n  * Auth Amount: %@", paramResponseData.authorizedAmount.stringValue];
    }
    if (paramError)
    {
        [s appendFormat:@"\nError: %@", paramError.localizedDescription];
    }
    [self updateStatusMessage:s];
}


/*
 ----------WARNING!----------------
 Finger print generation requires the transaction key. This should
 be done at the server. It is shown here only for Demo purposes.
 */
-(NSString*) buildFingerprintWithTransaction: (VMposTransactionObject*) transactionObject withMerchantId: (NSString*) merchantId {
    NSDate* dateNow = [NSDate date];
    NSString* fingerprintDateString = [MPDemoViewController formatFingerprintDate:dateNow];
    NSString* merchantTransKey = self.selectedAccountData[kKeyTransactionKey];
    NSString* fgComponents = [NSString stringWithFormat:@"%@%@%@%@%@", [MPDemoViewController stringSha1:merchantTransKey], merchantId, transactionObject.transactionCode, [transactionObject.totalAmount gatewayPriceString], fingerprintDateString];
    NSString* hashedFgComponents = [MPDemoViewController stringHmacSha256:fgComponents];

    return [NSString stringWithFormat:@"%@#%@", hashedFgComponents, fingerprintDateString];
}

+(NSString*) formatFingerprintDate: (NSDate*) date {
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    NSTimeZone* tz = [NSTimeZone timeZoneWithName:@"UTC"];
    [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
    [dateFormatter setTimeZone:tz];

    return [dateFormatter stringFromDate:date];
}

+ (NSString *)stringSha1:(NSString *)value
{
    const char *cstr = [value cStringUsingEncoding:NSUTF8StringEncoding];
    NSData *data = [NSData dataWithBytes:cstr length:value.length];
    uint8_t digest[CC_SHA1_DIGEST_LENGTH];

    // This is an iOS5-specific method.
    // It takes in the data, how much data, and then output format, which in this case is an int array.
    CC_SHA1(data.bytes, (uint)data.length, digest);

    return [self stringHexEncode:digest withLength:CC_SHA1_DIGEST_LENGTH];
}

+ (NSString *)stringSha256:(NSString *)value
{
    const char *cstr = [value cStringUsingEncoding:NSUTF8StringEncoding];
    NSData *data = [NSData dataWithBytes:cstr length:value.length];
    uint8_t digest[CC_SHA256_DIGEST_LENGTH];

    // This is an iOS5-specific method.
    // It takes in the data, how much data, and then output format, which in this case is an int array.
    CC_SHA256(data.bytes, (uint)data.length, digest);

    return [self stringHexEncode:digest withLength:CC_SHA256_DIGEST_LENGTH];
}

+ (NSString *)stringHmacSha256:(NSString *)value
{
    CCHmacContext ctx;
    const char* utf8ValueString = [value UTF8String];
    uint8_t hmacData[CC_SHA256_DIGEST_LENGTH];

    CCHmacInit(&ctx, kCCHmacAlgSHA256, utf8ValueString, strlen(utf8ValueString));
    CCHmacUpdate(&ctx, utf8ValueString, strlen(utf8ValueString));
    CCHmacFinal(&ctx, hmacData);

    return [self stringHexEncode:hmacData withLength:CC_SHA256_DIGEST_LENGTH];
}

+(NSString*) stringHexEncode: (uint8_t*) data withLength: (NSInteger) dataLength {
    NSMutableString* output = [NSMutableString stringWithCapacity:dataLength * 2];

    // Parse through the CC_SHA256 results (stored inside of digest[]).
    for(int i = 0; i < dataLength; i++) {
        [output appendFormat:@"%02x", data[i]];
    }

    return output;
}

+ (NSString*)base64forData:(NSData*)theData {

    const uint8_t* input = (const uint8_t*)[theData bytes];
    NSInteger length = [theData length];

    static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
    uint8_t* output = (uint8_t*)data.mutableBytes;

    NSInteger i;
    for (i=0; i < length; i += 3) {
        NSInteger value = 0;
        NSInteger j;
        for (j = i; j < (i + 3); j++) {
            value <<= 8;

            if (j < length) {
                value |= (0xFF & input[j]);
            }
        }

        NSInteger theIndex = (i / 3) * 4;
        output[theIndex + 0] =                    table[(value >> 18) & 0x3F];
        output[theIndex + 1] =                    table[(value >> 12) & 0x3F];
        output[theIndex + 2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';
        output[theIndex + 3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';
    }

    return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] ;
}

我可以从哪里得到所有这些值。如果有人列出通过 Cyber​​Source 进行 Apple 支付集成所涉及的所有步骤,我们将不胜感激。另外请不要将我推荐给苹果开发者,因为我已经在 Apple Developer 上阅读了有关 Apple Pay 的详细信息。

4

0 回答 0