iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
永豐金融APIs

30天全端挑戰!React+Spring Boot+Mongo DB 串接永豐API 打造金融網站系列 第 21

[Day 21] - 初探永豐銀行線上收款API - 實作我的收款API

  • 分享至 

  • xImage
  •  

昨晚在測試時遇到一個問題找了好久,就是我的QpayHelper這支程式裡明明有用constructor injection
執行時卻報nullpointer的錯
開debug mode發現,我autowired的Bean是null...

找了好久都不知道哪邊有問題,結果發現原來是因為我在另一支程式在call QpayHelper時
是用new的方式新增實例,
原來這麼做會導致裡面沒有被autowired到...又學到了一課/images/emoticon/emoticon20.gif

今天要來實作要拿來給我的網站使用的API

因為永豐的API在建立訂單時,需要不重複的訂單編號,而在MongoDB似乎沒有get Sequence的功能
因此我打算先建立一個取流水號的功能,

首先,一樣先建立一個Data Object

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import lombok.Data;

@Data
@Document
public class NextNum {
    @Id
    private String id;
    private long no;
}

再來是repostory

import com.rei1997.vault.model.entity.NextNum;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface NextNumRepo extends MongoRepository<NextNum,String>{
}

最後再建一個service就完成了

@RequiredArgsConstructor
@Service
public class NextNumService {
    
    private final NextNumRepo nextNumRepo;
    public long getNum(){
        Optional<NextNum> num=nextNumRepo.findById("no");
        long nextNum=0;
        if(num.isPresent()){
            nextNum=num.get().getNo()+1;
            num.get().setNo(nextNum);
            nextNumRepo.save(num.get());;
        }else{
            NextNum n=new NextNum();
            n.setId("no");
            n.setNo(1);
            nextNum=n.getNo();
            nextNumRepo.save(n);
        }
        return nextNum;
    }

這麼做是建立一個document來專忙放我的編號,
並且在每次取號後都+1,不過我不確定這麼做是不是個好作法...
搞不好會有重複取號的問題呢...晚點再回來看看有沒有更好的做法

因為我覺得之前做好的QpayHelper就等於是Service了
接下來就來直接實作Controller

我後來先把QpayHelper的qpayHelper方法回傳值改成String,直接回傳json字串,要取哪些欄位來呈現就由前端去操作吧!
因為確定都只回傳json字串,所以我在PostMapping直接加上了
produces = MediaType.APPLICATION_JSON_VALUE
也就是告訴瀏覽器 回傳的資料是application/json格式

import com.rei1997.vault.api.Qpay.QpayHelper;
import com.rei1997.vault.api.Qpay.OrderCreate.OrderCreateReq;
import com.rei1997.vault.api.Qpay.OrderPayQuery.OrderPayQueryReq;
import com.rei1997.vault.service.NextNumService;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.MediaType;

import lombok.RequiredArgsConstructor;

@RestController
@RequestMapping(value="api/v1/Qpay",produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
public class QpayController {
    private final QpayHelper qpayHelper;
    private final NextNumService service;
    
    @PostMapping("/")
    public String orderCreate(@RequestBody OrderCreateReq orderCreateReq){
//有些value由後端控制
        cardParam.setAutoBilling(AutoBilling.Y);
        orderCreateReq.setShopNo("NA0249_001");
        orderCreateReq.setOrderNo(String.valueOf(service.getNum()));
        orderCreateReq.setCurrencyID("TWD");
        orderCreateReq.setCardParam(cardParam);
        orderCreateReq.setReturnURL("http://localhost:8080/demo/api/v1/Qpay/query");
        String jsonRes="";
        try {
            jsonRes=qpayHelper.qpayHelper(orderCreateReq, "OrderCreate");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.err.println(e.toString());
        }
        return jsonRes;


    }

    @PostMapping("/query")
    public String orderPayQuery(@RequestBody OrderPayQueryReq orderPayQueryReq){

        String jsonRes="";
        try {
            jsonRes=qpayHelper.qpayHelper(orderPayQueryReq, "OrderPayQuery");
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println(e.toString());
        }
        return jsonRes;
    }
}

好,驗收!
https://ithelp.ithome.com.tw/upload/images/20211007/20128973MvhLu6aRXa.png

拿取得的url來貼瀏覽器
成功來到付款頁https://ithelp.ithome.com.tw/upload/images/20211007/20128973HATDZxUy1D.png

本來付款完成後預計是會跳轉到付款結果的api
結果
https://ithelp.ithome.com.tw/upload/images/20211007/20128973ZpVqltCM5Z.png
發現原來因為永豐跳轉時post到我的api的值是用post param的格式,而非json
我用的@ReuestBody沒辦法接收
因此改成@RequestParam

    @PostMapping("/query")
    public String orderPayQuery(@RequestParam Map<String,String>params){
    ...略

害我又要再用ObjectMapper轉一次...

        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(Include.NON_NULL);
        OrderPayQueryReq orderPayQueryReq=
        mapper.convertValue(params, OrderPayQueryReq.class);
        String jsonRes="";

又發現因為永豐給的key是大寫開頭,Objectmapper無法識別,
找到一個方法是再加上
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
讓轉換時不要區分大小寫

@PostMapping("/query")
public String orderPayQuery(@RequestParam Map<String,String>params){

    ObjectMapper mapper = new ObjectMapper();
    mapper.setSerializationInclusion(Include.NON_NULL);
    mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
    OrderPayQueryReq orderPayQueryReq=
    mapper.convertValue(params, OrderPayQueryReq.class);
    String jsonRes="";
    try {
        jsonRes=qpayHelper.qpayHelper(orderPayQueryReq, "OrderPayQuery");
    } catch (Exception e) {
        e.printStackTrace();
        System.err.println(e.toString());
    }
    return jsonRes;
}

https://ithelp.ithome.com.tw/upload/images/20211007/201289731afb8ICL6d.png

拖了這麼多天終於成功啦/images/emoticon/emoticon02.gif


上一篇
[Day 20] - 初探永豐銀行線上收款API - 訂單查詢及其他(2)
下一篇
[Day 22] - React 環境建置
系列文
30天全端挑戰!React+Spring Boot+Mongo DB 串接永豐API 打造金融網站30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言