---
# System prepended metadata

title: Hinet小額付費ＡＰＩ

---

# Hinet小額付費ＡＰＩ

## 更新紀錄
* 2020/11/22 更新版本：20.11.11-SNAPSHOT
* 2020/11/22 加入HttpClient Timeout設定
* 2020/11/16 更新版本：20.11.6-SNAPSHOT
* 2020/11/16 防止啟動失敗
* 2020/11/06 更新版本：20.10.11-SNAPSHOT
* 2020/11/06 判斷HiTOPS帳號不能使用於正式區(HiTOPS43除外)。

## 使用說明
### 一、設定
1. 使用common-api-fwk: 20.10.10
```
<dependency>
    <groupId>geps3</groupId>
    <artifactId>common-api-fwk</artifactId>
    <version>20.10.10-SNAPSHOT</version>
</dependency>
```
2. WebConfig.java加上"geps3.pms.qdcs.common"
![](https://i.imgur.com/P7fILVv.jpg)


### 二、使用HinetAAAClient
```
@Autowired
private HinetAAAClient aaaClient;
```

### 三、一般小額付費流程(1A->2A->3A)
> **領標較為複雜將於第四節另外敘述流程**
#### 1A認證(Authentic)
1.傳入產品代碼、網址、費用產生1A認證參數(AaaAuthenticRq)，組成HTML form送出，將使用者網頁導向小額付費網站進行認證。
```
AaaAuthenticRq authenticRq = 
    aaaClient.getAuthenticRequest(productId, curl, eurl, fee);
request.setAttribute("aaRequestURL", authenticRq.getRequestURL()); // 小額支付認證介面網址
request.setAttribute("aaVersion", authenticRq.getVersion()); // 系統版本
request.setAttribute("aaProductId", authenticRq.getProductId()); 
request.setAttribute("aaCurl", authenticRq.getCurl());
request.setAttribute("aaEurl", authenticRq.getEurl()); 
request.setAttribute("aaFee", authenticRq.getFee());
request.setAttribute("aaOthers", authenticRq.getOthers()); // 廠商自訂參數(目前均設為"others")
request.setAttribute("aaSum", authenticRq.getSum()); // MD5驗證碼
...
```
> productId：產品代碼(領標288983、報價289013...)。
> curl：認證成功後返回網址，如: http://myhost/qdcs/paySuccess。
> eurl：認證失敗時返回網址。
> fee：產品費用。

```
JSP:
<form method="post" action="${aaRequestURL}" id="a1PaymentForm">
	<input type="hidden" name="aa-version" value="${aaVersion}">
	<input type="hidden" name="aa-productid" value="${aaProductId}">
	<input type="hidden" name="aa-curl" value="${aaCurl}">
	<input type="hidden" name="aa-eurl" value="${aaEurl}">
	<input type="hidden" name="aa-fee" value="${aaFee}">
	<input type="hidden" name="aa-others" value="${aaOthers}">
	<input type="hidden" name="aa-sum" value="${aaSum}">
</form>
```

網頁送出後導向中華支付，使用者輸入帳號密碼認證>送出後導回指定的Curl(錯誤則為Eurl)。
![](https://i.imgur.com/anKLkGU.png)

認證成功導向回指定的curl後，要繼續進行2A授權。

#### 2A授權(Authorize)
Controller接收支付成功導回的訊息，解析回傳的訊息。
```
@RequestMapping("/paySuccess")
public paySuccess() {

    String productId = "289013";

    AaaAuthenticRs authenticRs = aaaClient.parseAuthenticRs(request);
    if (authenticRs.isSuccess()) {
       // 認證成功
       String otpw = authenticRs.getOtpw();
       ...
    }
 
...
}
```
確認認證成功，可取得認證授權碼otpw，以此授權碼進行2A授權。
```
AaaAuthAcctRs authorizeRs =
    aaaClient.sendAuthorizeRq(authenticRs.getOtpw(), authenticRs.getFee(),
        authenticRs.getAuthority(), productId);

if (authorizeRs.isSuccess) {
    // 授權成功
    ...
}
```

#### 3A扣款(Account)
2A授權成功後，最後進行3A扣款(**此步驟完成才算真正付費扣款成功**)。
```
String serviceRemark = model.getTenderOrgId() + "_000"
        + "^" + model.getTenderCaseNo() + "^" + model.getTenderSq() 
        + "^00^" + tokenNo + "^" + getUserIp();
        
AaaAuthAcctRs accountingRs = aaaClient
    .sendAccountingRq(authenticRs.getOtpw(), authenticRs.getFee(),
        authenticRs.getAuthority(), stime, serviceRemark, productId);
        
if (accountingRs.isSuccess()) {
    // 至此小額支付扣款成功，可進行付款資料儲存紀錄
    service.saveEqmToken(eqmToken);
}     
```
> stime：當前消費（啟始）時間(yyyyMMddHHmmss)。
> serviceRemark：服務備註，使用者自訂用來識別服務的資訊，建議用^分隔。

#### 取得帳號餘額(RemainQuota)
如需取得使用之帳號餘額
```
AaaRemainQuotaRs remainQuota =
    aaaClient.getRemainQuota(authenticRs.getUid(),
        authenticRs.getHn(), productId);
if(remainQuota.isSuccess()) {
    String quota = remainQuota.getRemainingQuota(); // 如:"9999.00"
    ...
}
```
> uid、hn為1A返回之參數取得，兩者可擇一輸入，如都有輸入則以uid為優先。

### 四、電子領標付費流程
電子領標由於有三個產品代碼，付款流程如下：
1. 1A以產品代碼288983(正式、練習相同這組)產生認證參數，然後導向支付網頁。
```
AaaAuthenticRq authenticRq = 
    aaaClient.getAuthenticRequest("288983", curl, eurl, fee);
```
> fee：這邊的費用等於招標設定(TPAM_TENDER_MAIN)的系統使用費(SYSTEM_CHARGE)+招標文件費(DEPT_CHARGE)+文件代收費(DOC_CHARGE)
2. 認證成功後導回Controller，取得認證授權碼(otpw)，接著進行各項產品授權，先以1A的產品代碼及費用呼叫2A確認授權成功。
```
AaaAuthAcctRs authorizeRs =
    aaaClient.sendAuthorizeRq(authenticRs.getOtpw(), authenticRs.getFee(),
        authenticRs.getAuthority(), "288983");
```
> 經測試費用比照二代傳0也可以
3. 接著判斷招標設定的三項費用，如果有收取，則以該項產品代碼及費用先進行交換授權碼(APA1)，再進行2A授權。
```
List<AaaAuthAcctRs> authAcctList = new ArrayList<>();
if (tpam.systemCharge>0) {

    AaaExchangeOtpwRs xchgOtpwRs = aaaClient.sendAPA1Rq(authenticRs.getOtpw(), tpam.systemCharge,
            authenticRs.getAuthority(), sysProductId);
    if (!xchgOtpwRs.isSuccess()) {
        throw new Exception("...");
    }

    String newOtpw = xchgOtpwRs.getNewOtpw();
    AaaAuthAcctRs authorizeSys =
        aaaClient.sendAuthorizeRq(newOtpw, tpam.systemCharge,
            authenticRs.getAuthority(), sysProductId);
    authAcctList.add(authorizeSys);
}

if (tpam.deptCharge>0) {
    AaaAuthAcctRs authorizeDept =
        aaaClient.sendAuthorizeRq(authenticRs.getOtpw(), tpam.deptCharge,
            authenticRs.getAuthority(), deptProductId);
    authAcctList.add(authorizeDept);
}

if (tpam.docCharge>0) {
    AaaAuthAcctRs authorizeDoc =
        aaaClient.sendAuthorizeRq(authenticRs.getOtpw(), tpam.docCharge,
            authenticRs.getAuthority(), docProductId);
    authAcctList.add(authorizeDoc);
}
```
> ProductId：系統使用費288990/288984(練習區)、招標文件費288991/288987(練習區)、文件代收費288992/288988(練習區)。
4. 2A授權成功後，同樣分別進行3A扣款(參考上述3A扣款)。
```
String tokenNo = service.createToken();

for (AaaAuthAcctRs authAcct: authAcctList) {
    AaaAuthAcctRs accountingRs = aaaClient
        .sendAccountingRq(authenticRs.getOtpw(), fee,
            authenticRs.getAuthority(), stime, serviceRemark, productId);
    if(!accountingRs.isSuccess()) {
        service.deleteToken(tokenNo);
        ...
        break;        
    }
}
```
> otpw、authority均為1A時取得；fee、productId則為2A根據費用類型有所不同
> 領標時，各項費用3A扣款如有某次失敗則**視為失敗**，需刪除系統已記錄之領標憑據。

5. 根據已經產生之憑據，可提供使用者下載憑據檔案與其他相關作業。

###### tags: GEPS3 AAA 小額