Visaの新サービス(Visa Developer)のサンプルコードをSwiftに変換してみた。

2016.02.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

本日お昼に、「Visaの新サービス(Visa Developer)のサンプルコードをObjective−Cに変換してみた。」というタイトルでブログを書いたのですが、某所から「Swiftも」という声を頂いたので書きました。

Visa Developerのサービスの詳しい情報はは、先のページをご参照ください。

2 Swift版

Objective-C版を、そのままSwiftのプロジェクトにコピーして、エラーが無くなるまで変換しました。 あまり、Swiftらしい書き方には拘らず、あくまで、本家のサンプルに近い形になっています。

当然というば当然ですが、他の言語から移植するのとは、作業量が圧倒的に違います。

@IBAction func tapButton(sender: AnyObject) {


    let baseUri = "cybersource/"
    let resourcePath = "payments/v1/authorizations"
    let url = "https://sandbox.api.visa.com/\(baseUri)\(resourcePath)?apikey=\(API_KEY)"
    let body = "{\"amount\": \"0\", \"currency\": \"USD\", \"payment\": { \"cardNumber\": \"4111111111111111\", \"cardExpirationMonth\": \"10\", \"cardExpirationYear\": \"2016\" }}"
    let xPayToken = getXPayToken(resourcePath, queryString: "apikey=\(API_KEY)", requestBody: body) as String

    let request = NSMutableURLRequest(URL: NSURL(string: url)!)
    request.HTTPMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue(xPayToken, forHTTPHeaderField: "x-pay-token")


    let postBody = NSMutableData()
    postBody.appendData(body.dataUsingEncoding(NSUTF8StringEncoding)!)
    request.HTTPBody = postBody

    let session = NSURLSession.sharedSession()
    let task = session.dataTaskWithRequest(request) {
        (
        let data, let response, let error) in
        guard let _:NSData = data, let _:NSURLResponse = response  where error == nil else {
            print("Error")
            return
        }

        let responseString:NSString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
        print(responseString)

        dispatch_async(
            dispatch_get_main_queue(),
            {
                self.textView.text = responseString as String
            }
        );
    }
   task.resume()
}

func getXPayToken(apiNameURI:NSString, queryString:NSString, requestBody:NSString) -> NSString {
    let timestamp = getTimestamp()
    let sourceString = "\(SHARED_SECRET)\(timestamp)\(apiNameURI)\(queryString)\(requestBody)"
    let hash = getDigest(sourceString)
    return "x:\(timestamp):\(hash)"
}

func getTimestamp() -> NSString {
    let date = NSDate().timeIntervalSince1970
    return NSString(format: "%.0f", date)
}

func getDigest(date:NSString) -> NSString {
    if let d = date.dataUsingEncoding(NSASCIIStringEncoding) {
        var bytes = [UInt8](count: 64, repeatedValue: 0)
        CC_SHA256(d.bytes, CC_LONG(d.length), &bytes)
        let digest = NSMutableString(capacity: 64)
        for var i=0; i<32; i++ {
            digest.appendFormat("%02x", bytes[i])
        }
        return digest
    }
    return ""
}

Objective-Cと比較して、行数は同じぐらいですが、やっぱり文字数はかなり少ない感じ・・・

github サンプルコード(https://github.com/furuya02/CybersourceSampleSwift/blob/master/CybersourceSampleSwift/ViewController.swift)

3 最後に

実は、今回も認証エラー(401)で、少し悩みました。

結果的には、変換中に変数を1個消してしまっていただけなので、慎重にやってれば、嵌らなかった筈です。

しかし、このように、サーバ側から詳しいエラーの原因を得られない場合は、作業に一定の時間がかかることを見積もる必要があるかも知れません。

もう少しで、飛行機出発します。 それまでに、Submitできてよかったです。