昨晚在測試時遇到一個問題找了好久,就是我的QpayHelper這支程式裡明明有用constructor injection
執行時卻報nullpointer的錯
開debug mode發現,我autowired的Bean是null...
找了好久都不知道哪邊有問題,結果發現原來是因為我在另一支程式在call QpayHelper時
是用new的方式新增實例,
原來這麼做會導致裡面沒有被autowired到...又學到了一課
今天要來實作要拿來給我的網站使用的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;
}
}
好,驗收!
拿取得的url來貼瀏覽器
成功來到付款頁
本來付款完成後預計是會跳轉到付款結果的api
結果
發現原來因為永豐跳轉時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;
}
拖了這麼多天終於成功啦