sofort 支付 版本sofort/開發語言java/使用場景PC端網站

一、註冊sofort 交易賬號

註冊中須填公司基本信息、綁定銀行卡等,個人感覺讓財務或行政做就行了,開發人員就不要搞了

https://www.sofort.com/integrationCenter-eng-DE/content/view/full/4520此鏈接是sofort關於註冊、項目創建等的引導說明,按照步驟來就行了。

創建項目有Gateway project 和 Classic project兩種,一般選擇Gateway project 即可。測試模式當然要勾選,方便測試。 notificationURL 、successURL 、 abortURL 、 timeoutURL要根據項目實際情況填寫,注意最好是https路徑哦。

創建完項目後只能測試用,需要你激活項目才能用於生產環境。

創建完後在My projects頁面,點擊你創建的項目,進入下圖頁面,Base setting窗口有你代碼中需要的customerId、projectId和apiKey,Test the project窗口有你測試需要銀行信息。



二、API類型選擇及源碼下載

https://www.sofort.com/integrationCenter-eng-DE/integration/API-SDK/#2861-sue此鏈接API類型選擇及源碼下載

下圖選擇API版本


下圖源碼下載及跳轉到API文檔頁面,源碼是gradle構建的,習慣maven的朋友百度搜下gradle的基本使用即可。(本人項目是電子商務網站,所以選擇的是Sofort版,語言是java)


開發前建議先看看API文檔,另外sofort有點坑,沒有可用的sdk jar包,需要你下載源碼後自己打成jar包。

三、寫代碼嘍

直接參照sofort給的示例寫就可以了。如下如目錄:


四、本人代碼

1、支付接口(跟sofort實例代碼基本一樣,只是方法變成靜態方便調用,另外交易ID存入session方便回調獲取session信息)

package com.aurorascm.pay;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.apache.shiro.session.Session;
import com.aurorascm.util.Jurisdiction;
import com.sofort.lib.core.internal.net.ConnectionException;
import com.sofort.lib.core.internal.net.http.HttpAuthorizationException;
import com.sofort.lib.core.internal.net.http.HttpConnectionException;
import com.sofort.lib.core.internal.transformer.RawResponse;
import com.sofort.lib.core.internal.transformer.RawResponse.Status;
import com.sofort.lib.core.internal.utils.StringUtilities;
import com.sofort.lib.core.products.request.parts.Notification;
import com.sofort.lib.core.products.response.SofortTransactionStatusNotification;
import com.sofort.lib.payment.DefaultSofortLibPayment;
import com.sofort.lib.payment.products.request.PaymentRequest;
import com.sofort.lib.payment.products.request.PaymentTransactionDetailsRequest;
import com.sofort.lib.payment.products.response.PaymentResponse;
import com.sofort.lib.payment.products.response.PaymentTransactionDetailsResponse;
import com.sofort.lib.payment.products.response.parts.PaymentTransactionDetails;
/**
 * An example of usage of the SofortLib Payment (SOFORT Überweisung).
 * 
 * 1st - use PaymentInitaliser to initialise a new payment
 * 
 * 2nd - start/resume/check listening on notificationUrls (see the SOFORT API
 * documentation)
 * 
 * 3rd - use the NotificationParser to parse and handle received status
 * notifications
 * 
 * 4th - use TransactionDetailsService to retrieve transaction details
 */
public class SofortPayment {

// https://域名/sofort/success(success-link)
// https://域名/sofort/abort(abort-link)
// https://域名/sofort/http_notification(HTTP_notification)
// https://域名/sofort/payment(Timeout-link)


// private static final ResourceBundle CORE_BUNDLE = ResourceBundle.getBundle("core");
private static final int customerId = 你的賬號ID;//Integer.parseInt(CORE_BUNDLE.getString("customerId"));
private static final int projectId = 你的項目ID;//Integer.parseInt(CORE_BUNDLE.getString("projectId"));
private static final String apiKey = "你的apiKey";//CORE_BUNDLE.getString("apiKey");
private static final String currency = "EUR";//貨幣單位


// private static final ResourceBundle PAYMENT_BUNDLE = ResourceBundle.getBundle("payment");
private static final String notificationURL = "https://域名/sofort/http_notification";//PAYMENT_BUNDLE.getString("notificationURL");
private static final String successURL = "https://域名/sofort/success";//PAYMENT_BUNDLE.getString("successURL");
private static final String abortURL = "https://域名/sofort/abort";//PAYMENT_BUNDLE.getString("abortURL");
private static final String timeoutURL = "https://域名/sofort/timeout";//PAYMENT_BUNDLE.getString("timeoutURL");


public static class PaymentInitialiser {


/**
* Start a sofort payment, check for errors and warnings and use the
* received payment url for redirection of the customer.

* @return the payment URL the customer have to be redirected to
*/
public static String sofortPayment(double amount) {
boolean consumerProtection = Boolean.TRUE;
String[] purposes = {"aurora-germany-trade"};
PaymentRequest paymentRequest = new PaymentRequest(projectId, amount, currency, Arrays.asList(purposes), consumerProtection)
.setNotificationUrls(Arrays.asList(new Notification(notificationURL)))
.setSuccessUrl(successURL)
.setAbortUrl(abortURL)
.setTimeoutUrl(timeoutURL);


// initialise a payment.
PaymentResponse paymentResponse = doRequest(paymentRequest);


// handle the transaction ID.
handlePayment(paymentResponse);

/**此處爲本人添加將交易ID放入session,在成功路徑中獲取交易信息。像支付寶、paypal能直接取得交易信息,但sofort試了很久沒有找出辦法,只得放session中,另外支付寶、paypal回調後session是失效的,但是sofort 回調後session沒有失效。可能就是這樣取交易信息吧。*/
String transId = paymentResponse.getTransId();

Session session = Jurisdiction.getSession(); 

String key = Jurisdiction.getCustomerID() + "sofortTransId";
session.setAttribute(key, transId);


// redirection URL.
return paymentResponse.getPaymentUrl();
}
private static PaymentResponse doRequest(PaymentRequest paymentRequest) {
PaymentResponse paymentResponse;
try {
paymentResponse = new DefaultSofortLibPayment(customerId, apiKey).sendPaymentRequest(paymentRequest);
} catch (HttpAuthorizationException e) {
System.err.println("The authorization with the given apiKey has been failed.");
throw e;
} catch (HttpConnectionException e) {
System.err.println("The HTTP communication has been failed. Response/status code: " + e.getResponseCode());
throw e;
} catch (ConnectionException e) {
System.err.println("The communication has been failed.");
throw e;
}
// check and handle the response errors and warnings
if (paymentResponse.hasResponseErrors()) {
throw new IllegalStateException("Initialization errors: " + new StringUtilities().glue(paymentResponse.getResponseErrors(), " /// "));
}
if (paymentResponse.hasResponseWarnings()) {
System.err.println("Initialisation warnings: " + new StringUtilities().glue(paymentResponse.getResponseWarnings(), " /// "));
}
// check and handle the payment errors and warnings
if (paymentResponse.hasResponsePaymentErrors()) {
throw new IllegalStateException("Could not initialize a sofort payment. Errors: " + new StringUtilities().glue(paymentResponse.getResponsePaymentErrors(), " /// "));
}
if (paymentResponse.hasNewPaymentWarnings()) {
System.err.println("Initialisation of a new payment warnings: " + new StringUtilities().glue(paymentResponse.getNewPaymentWarnings(), " /// "));
}
return paymentResponse;
}
private static void handlePayment(PaymentResponse paymentResponse) {
// handle initialised payment, i.e. store transId into DB
}
}
public static class NotificationParser {
/**
* Parse the received transaction changes notification.

* @param statusNotification
*            received status notification
* @param status
* @return
*/
public SofortTransactionStatusNotification parseManualReceivedStatusNotification(Status status, String statusNotificationRaw) {
SofortTransactionStatusNotification statusNotification = new DefaultSofortLibPayment(customerId, apiKey).parseStatusNotificationResponse(new RawResponse(status, statusNotificationRaw));
// check and handle the response errors and warnings
if (statusNotification.hasResponseErrors()) {
throw new IllegalStateException("Parsed status notification contains errors. Errors: " + new StringUtilities().glue(statusNotification.getResponseErrors(), " /// "));
}
if (statusNotification.hasResponseWarnings()) {
System.err.println("Parsed status notification contains warnings. Warnings: " + new StringUtilities().glue(statusNotification.getResponseWarnings(), " /// "));
}
return statusNotification;
}
}
public static class TransactionDetailsService {
/**
* Get transaction details for a transaction.

* @param transIds
*            - transaction ids
* @return list of transaction details
*/
public static List<PaymentTransactionDetails> getDetails(String... transIds) {
PaymentTransactionDetailsRequest transactionRequest = new PaymentTransactionDetailsRequest()
.setTransIds(Arrays.asList(transIds));
return doRequest(transactionRequest).getTransactions();
}
/**
* Get transaction details for a time span.

* @param from
*            start date
* @param to
*            end date

* @return list of transaction details
*/
public List<PaymentTransactionDetails> getDetails(Date from, Date to) {
PaymentTransactionDetailsRequest transactionRequest = new PaymentTransactionDetailsRequest()
.setFromTime(from)
.setToTime(to);
return doRequest(transactionRequest).getTransactions();
}
private static PaymentTransactionDetailsResponse doRequest(PaymentTransactionDetailsRequest transactionRequest) {
PaymentTransactionDetailsResponse transactionDetailsResponse;
try {
transactionDetailsResponse = new DefaultSofortLibPayment(customerId, apiKey).sendTransactionDetailsRequest(transactionRequest);
} catch (HttpAuthorizationException e) {
System.err.println("The authorization with the given apiKey has been failed.");
throw e;
} catch (HttpConnectionException e) {
System.err.println("The HTTP communication has been failed. Response/status code: " + e.getResponseCode());
throw e;
} catch (ConnectionException e) {
System.err.println("The communication has been failed.");
throw e;
}
// check and handle the response errors
if (transactionDetailsResponse.hasResponseErrors()) {
throw new IllegalStateException("Initialization errors: " + new StringUtilities().glue(transactionDetailsResponse.getResponseErrors(), " /// "));
}
if (transactionDetailsResponse.hasResponseWarnings()) {
System.err.println("Initialisation warnings: " + new StringUtilities().glue(transactionDetailsResponse.getResponseWarnings(), " /// "));
}=
return transactionDetailsResponse;
}
}
}

2、控制器

package com.aurorascm.controller.pay;

import java.io.IOException;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.shiro.session.Session;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.xml.sax.SAXException;
import com.aurorascm.controller.base.BaseController;
import com.aurorascm.pay.SofortPayment;
import com.aurorascm.util.Jurisdiction;
import com.sofort.lib.core.internal.transformer.RawResponse.Status;
import com.sofort.lib.payment.products.response.parts.PaymentStatus;
import com.sofort.lib.payment.products.response.parts.PaymentTransactionDetails;


/** Sofort支付控制器
 * @author 
 * @version 1.0
 */
@Controller
//
@RequestMapping(value="/sofort")
public class SofortCommonController extends BaseController {


/**Sofort 支付接口
* @author BYG/2018.1.10
* @param String orderID;
* @return String sofortPayUrl;
* @throws Exception
*/
@RequestMapping(value="/payment", produces="application/json;charset=UTF-8")
@ResponseBody
public String sofortPayment(String orderID)throws Exception{
//    BigDecimal shouldPayment = orderServiceImpl.getShouldPayByOID(orderID);//訂單實際應付金額
//    double amount = shouldPayment.doubleValue();
double amount = 1;
String sofortPayUrl = SofortPayment.PaymentInitialiser.sofortPayment(amount);//sofort 支付路徑
logger.info("sofort-sofortPayment-" + sofortPayUrl);
return sofortPayUrl;
}

/**Sofort 支付成功
* @author BYG/2018.1.10
* @param 
* @throws ParserConfigurationException 
* @throws IOException 
* @throws SAXException 
*/
@RequestMapping(value="/success", produces="application/xml;charset=UTF-8")
@ResponseBody
    public String success() throws ParserConfigurationException{
Session session = Jurisdiction.getSession(); 
String key = Jurisdiction.getCustomerID() + "sofortTransId";
String transId = session.getAttribute(key).toString();
String[] transIds = {transId};
List<PaymentTransactionDetails> transactions = SofortPayment.TransactionDetailsService.getDetails(transIds);
double amount = transactions.get(0).getAmount();
PaymentStatus status = transactions.get(0).getStatus();
return null;
    }

/**sofort 通知
* @author 
* @param 
* @throws ParserConfigurationException 
* @throws Exception
*/
@RequestMapping(value="/http_notification", produces="application/xml;charset=UTF-8")
@ResponseBody
    public void http_notification(Status status, String statusNotificationRaw) throws ParserConfigurationException{
/** 很遺憾沒有想到獲取異步通知信息的方法*/
}

/**Sofort 支付中止
* @author
* @param 
*/
@RequestMapping(value="/abort", produces="application/json;charset=UTF-8")
    public String abort(ModelMap modelMap){
/** 支付成功   */
modelMap.put("payResult", "abort");
return "system/pay/sofort/abort";
    }

/**Sofort 支付超時
* @author 
* @param 
*/
@RequestMapping(value="/timeout", produces="application/json;charset=UTF-8")
    public String timeout(ModelMap modelMap){
/** 支付成功   */
modelMap.put("payResult", "timeout");
return "system/pay/sofort/timeout";
    }

}

最後很遺憾我們公司沒有接sofort,因爲sofort激活需要網站有德語版,我們小公司沒有時間搞啊。。。另外吐槽下sofort客服,跟客服的溝通是我欲哭無淚。。。。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章