Ch13-1 : Change Email
[Email]
修改電子信箱這個功能,首先我們要先回顧我們原本的表單設計,member_main這個table,我們把email,這個欄位當作UNIQUE KEY使用,我們要讓這個欄位是唯一的資料,所以使用者修改電子信箱時,必須符合當時申請帳號的規範,該電子信箱不可重覆,只能存在一筆資料,在我們的資料庫,保證這個電子信箱,只會對應到一個人的帳號。
我們需要設計一個新的表單,去儲存使用者要修改的電子信箱,並且分成兩個階段,第一個階段是,輸入新電子信箱後,進行一些基本檢核,確認無誤之後,會寄送修改電子信箱信件到新信箱。第二階段是,我們需要從新的信箱,去點選修改密碼連結後,回到我們網站,我們網站需要輸入信件內的驗證碼,確保這份信件的正確性,若都填寫正確,將會更新相關表單,最後寄送修改電子信箱成功信到使用的新信箱。
[設計階段]
設計修改電子信箱,分成兩個兩階段,而每一個階段,都有兩個主要步驟需要處理,以及檢驗資料是否正確,以下是我設計出來的流程。
第一個階段
兩個主要步驟,拆分成使用者點選信箱功能時,首先要先出現原本電子信箱,已寄送修改新的電子信箱,還有使用者要自己填寫要修改的信箱,這部分會是1-1所要達成的項目。之後1-2所要達成的目標是,使用者填寫新的電子信箱時,需要檢核相關資訊是否正確,,確保使用者可以用新的電子信箱,進行後續驗證動作。還有一點要特別注意,這兩個動作都需要在登入狀態下,才能完成。
Stage 1-1
點選修改信箱功能,顯示相關資訊
若有尚未修改信箱且尚未逾期,也會顯示在畫面上
Step 1 : 驗證是否是登入狀態中(AuthCheck)
Step 2 : 抓取使用者memberNo
Step 3 : 抓取使用者註冊信箱,尚未認證信箱
Ok : 顯示修改信箱頁面
---
Stage 1-2
開始進行修改電子信箱資料驗整
Step 1 : 驗證是否是登入狀態中(AuthCheck)
Step 2 : 是否有填新信箱
Step 3 : 信箱是否有填寫
Step 4 : 信箱檢查是否使用中
OK 1 : 產生更換信箱相關資料
Ok 2 : 寫入更換信箱表單
Ok 3 : 寄送更換信箱認證碼信件
第二個階段
一樣有兩個主要的步驟。第一個階段,最後完成時,會寄送修改電子信箱連結,當使用者點選信件修改信箱連結時,會檢核連結是否正確。連結檢驗證正確之後,使用者需要填入信件的驗證碼,確保我們寄到的電子信箱是正確無誤的,之後才會進行更新會員電子信箱動作。
Stage 2-1
重設電子信箱信件寄送回來後,顯示相關資訊
Step 1 : 檢查電子信箱信件連結是否有資料
Step 2 : 檢查Token,是否可以查詢到會員資料
Step 3 : 檢查Token,是否使用過了
Step 4 : 檢查Token,是否逾期了
OK : 檢查通過,可以進行重設電子信箱動作,並把Token儲存在表單裡
---
Stage 2-2
開始進行修改電子信箱資料驗證
Step 1 : 檢查電子信箱信件連結是否有資料
Step 2 : 檢查Token,是否可以查詢到會員資料
Step 3 : 檢查Token,是否使用過了
Step 4 : 檢查Token,是否逾期了
Step 5 : 驗證碼是否正確
Ok 1 : 寫入會員修改資料紀錄
Ok 2 : 會員的電子信箱進行更新
Ok 3 : 會員修改電子信箱表單,更新成使用過
Ok 4 : 寄信到新的電子信箱,已更新
[相關表單]
member_changeEmail,會員修改信箱表單,當使用者使用修改信箱的功能時,將會紀錄到這個表單。
-- 會員修改信箱
-- member_changeEmail
-- member_no 會員編號 (索引鍵)
-- oldEmail 舊信箱
-- newEmail 新信箱
-- token 驗證字串
-- checkCode 驗證碼
-- isUse 是否使用過
-- createDate 創立日期
-- expiryTime 逾期時間
CREATE TABLE `member_changeEmail` (
`memberNo` VARCHAR(15) NOT NULL NULL COLLATE 'utf8_unicode_ci',
`oldEmail` VARCHAR(150) NOT NULL NULL COLLATE 'utf8_unicode_ci',
`newEmail` VARCHAR(150) NOT NULL NULL COLLATE 'utf8_unicode_ci',
`token` VARCHAR(150) NOT NULL NULL COLLATE 'utf8_unicode_ci',
`checkCode` VARCHAR(6) NOT NULL NULL COLLATE 'utf8_unicode_ci',
`isUse` BOOL NOT NULL NULL COLLATE 'utf8_unicode_ci',
`createDate` VARCHAR(50) NOT NULL NULL COLLATE 'utf8_unicode_ci',
`expiryDate` VARCHAR(50) NOT NULL NULL COLLATE 'utf8_unicode_ci',
CONSTRAINT pk_memberNo PRIMARY KEY (memberNo),
INDEX (token)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;
[相關程式路徑]
app
└ controllers
└ WebController.java <-- 新增ChangeEmail相關功能
└ pojo
└ web
└ email
└ MemberChangeEmail.java <-- 新增更換信箱pojo
MemberSendChangeEmail.java <-- 新增寄信相關pojo
└ views
└ web
└ headerNav.scala.html <-- 調整新增連結
└ loginSignup
└ authNewEmail.scala.html <-- 第二階段,修改信箱,點選信件回來時的驗證頁面
changeEmail.scala.html <-- 第一階段,修改信箱主頁面
changeEmailOk.scala.html <-- 第二階段,修改信箱成功頁面
sendChangeEmailOk.scala.html <-- 第一階段,申請修改信箱,寄信成功頁面
└ utils
└ signup
└ Utils_Signup.java <--- 新增ChangeEmail相關功能
Utils_Email.java <--- 新增寄信相關功能
└ services
└ Impl
└ WebServiceImpl.java <--- 實作WebService的新功能
└ WebService.java <--- 新增ChangeEmail相關功能
└ conf
└ routes <--- 新增相關服務路徑
└ services
└ WebService.xml <--- 新增相關SQL
[相關程式]
app.pojo.web.email.MemberChangeEmail.java
使用者一進入修改信箱頁面的時候,需要顯示的相關內容,我們設計成pojo來使用
package pojo.web.email;
public class MemberChangeEmail {
/** 原始信箱 */
private String originalEmail;
/** 尚未認證信箱 */
private String unAuthEmail;
/** 新信箱 */
private String newEmail;
public String getOriginalEmail() {
return originalEmail;
}
public void setOriginalEmail(String originalEmail) {
this.originalEmail = originalEmail;
}
public String getUnAuthEmail() {
return unAuthEmail;
}
public void setUnAuthEmail(String unAuthEmail) {
this.unAuthEmail = unAuthEmail;
}
public String getNewEmail() {
return newEmail;
}
public void setNewEmail(String newEmail) {
this.newEmail = newEmail;
}
}
app.pojo.web.email.MemberSendChangeEmail.java
使用者填寫修改信箱成功時,我們要記錄相關的欄位資訊,儲存到資料表member_changeEmail,轉換成pojo來方便我的使用。
package pojo.web.email;
public class MemberSendChangeEmail {
/** 會員編號*/
private String memberNo;
/** 原本信箱*/
private String oldEmail;
/** 新信箱*/
private String newEmail;
/** 信件token*/
private String token;
/** 驗證碼*/
private String checkCode;
/** 是否使用過*/
private boolean isUse;
/** 創立日期*/
private String createDate;
/** 逾期日期*/
private String expiryDate;
/** 資料庫時間*/
private String dbTime;
public String getMemberNo() {
return memberNo;
}
public void setMemberNo(String memberNo) {
this.memberNo = memberNo;
}
public String getOldEmail() {
return oldEmail;
}
public void setOldEmail(String oldEmail) {
this.oldEmail = oldEmail;
}
public String getNewEmail() {
return newEmail;
}
public void setNewEmail(String newEmail) {
this.newEmail = newEmail;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getCheckCode() {
return checkCode;
}
public void setCheckCode(String checkCode) {
this.checkCode = checkCode;
}
public boolean isUse() {
return isUse;
}
public void setUse(boolean isUse) {
this.isUse = isUse;
}
public String getCreateDate() {
return createDate;
}
public void setCreateDate(String createDate) {
this.createDate = createDate;
}
public String getExpiryDate() {
return expiryDate;
}
public void setExpiryDate(String expiryDate) {
this.expiryDate = expiryDate;
}
public String getDbTime() {
return dbTime;
}
public void setDbTime(String dbTime) {
this.dbTime = dbTime;
}
}
app.services.WebService.java
新增修改電子信箱相關服務
import pojo.web.email.MemberChangeEmail;
import pojo.web.email.MemberSendChangeEmail;
...
/** 更換信箱,撈取使用者信箱,尚未修改信箱 */
public MemberChangeEmail getMemberEmails(@Param("memberNo")String memberNo);
/** 寫入更換信箱相關資訊 */
public int genMemberSendChangeEmail(@Param("data")MemberSendChangeEmail data);
/** 撈取更換信箱表單相關資訊 */
public MemberSendChangeEmail getMemberSendChangeEmailByToken(@Param("token")String token);
/** 更新使用者的電子信箱 */
public int updateMemberEmail(@Param("memberNo") String memberNo, @Param("newEmail") String newEmail);
...
app.services.Impl.WebServiceImpl.java
新增修改信箱相關實作
import pojo.web.email.MemberChangeEmail;
import pojo.web.email.MemberSendChangeEmail;
...
@Override
public MemberChangeEmail getMemberEmails(@Param("memberNo") String memberNo) {
return this.webService.getMemberEmails(memberNo);
}
@Override
public int genMemberSendChangeEmail(MemberSendChangeEmail data) {
return this.webService.genMemberSendChangeEmail(data);
}
@Override
public MemberSendChangeEmail getMemberSendChangeEmailByToken(@Param("token")String token){
return this.webService.getMemberSendChangeEmailByToken(token);
}
@Override
public int updateMemberEmail(@Param("memberNo")String memberNo , @Param("newEmail")String newEmail){
return this.webService.updateMemberEmail(memberNo , newEmail);
}
...
conf.services.WebService.xml
新增相關SQL指令。
...
<!-- 更換信箱,撈取使用者信箱,尚未修改信箱,若有尚未修改信箱,且未逾期未使用,一樣顯示給使用者知道-->
<select id="getMemberEmails" parameterType="String" resultType="pojo.web.email.MemberChangeEmail">
SELECT
(SELECT email FROM member_main WHERE memberNo = #{memberNo} ) AS originalEmail ,
(SELECT newEmail FROM member_changeEmail
WHERE memberNo = #{memberNo} AND expiryDate > (DATE_FORMAT(NOW() , '%Y%m%d%H%i%s')) AND isUse = 0) AS unAuthEmail
FROM DUAL
</select>
<!-- 會員更換電子信箱表單 -->
<insert id="genMemberSendChangeEmail" parameterType="pojo.web.email.MemberSendChangeEmail">
insert into
member_changeEmail(memberNo , oldEmail , newEmail , token , checkCode , isUse , createDate , expiryDate)
values
(
#{data.memberNo} ,
#{data.oldEmail} ,
#{data.newEmail} ,
#{data.token} ,
#{data.checkCode} ,
#{data.isUse} ,
#{data.createDate} ,
#{data.expiryDate}
) ON DUPLICATE KEY UPDATE
memberNo = #{data.memberNo},
oldEmail = #{data.oldEmail},
newEmail = #{data.newEmail},
token = #{data.token},
checkCode = #{data.checkCode},
isUse = #{data.isUse},
createDate = #{data.createDate},
expiryDate = #{data.expiryDate}
</insert>
<!-- 使用會員編號與密碼確認該會員存在 -->
<select id="getMemberSendChangeEmailByToken" parameterType="String" resultType="pojo.web.email.MemberSendChangeEmail">
SELECT * , DATE_FORMAT(NOW(),'%Y%m%d%H%i%s') as dbTime FROM member_changeEmail WHERE token = #{token}
</select>
<!-- 更新會員電子信箱 -->
<update id="updateMemberEmail">
UPDATE member_main SET email = #{newEmail} WHERE memberNo = #{memberNo}
</update>
...
app.views.web.loginSignup.changeEmail.scala.html
第一階段,修改信箱主頁面,用來給使用者填入要修改的信箱。
@(data:pojo.web.email.MemberChangeEmail)
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>修改信箱</title>
@views.html.web.headerLibs()
@views.html.web.loginSignup.loginSignupLibs()
</head>
<body>
<div id="page-wrapper">
<div id="select_nav_user">@views.html.web.headerNav()</div>
</div>
<div class="form">
<ul class="tab-group">
<li class="tab active"><a>修改信箱</a></li>
</ul>
<div class="tab-content">
<div id="Form" >
<form action="@controllers.routes.WebController.changeEmail.url" method="post" id="changeEmailForm">
<div class="field-wrap">
<label class="lable-field-wrap">原本信箱</label>
<input type="text" required autocomplete="off" name="originalEmail" value="@if(data!=null && data.getOriginalEmail()!=null){@data.getOriginalEmail()}" readonly/>
</div>
@if(data!=null && data.getUnAuthEmail()!=null){
<div class="field-wrap">
<label class="lable-field-wrap">尚未認證新信箱</label>
<input type="text" required autocomplete="off" name="unAuthEmail" value="@data.getUnAuthEmail()" readonly/>
</div>
}
<div class="field-wrap">
<label class="lable-field-wrap">新信箱</label>
<input type="email" required autocomplete="off" name="newEmail"/>
</div>
@if(flash.containsKey("error")) {
<span style="color:red;">@flash.get("error")</span>
}
<a>
<input type="submit" value="SUBMIT" class="button button-block">
</a>
</form>
</div>
</div><!-- tab-content -->
</div> <!-- /form -->
<div id="titleBar"></div>
<script src='@routes.Assets.versioned("javascripts/loginSignup.js")'></script>
<script>
$( document ).ready(function() {
document.getElementById("editPasswordForm").reset();
});
</script>
</body>
</html>
app.views.web.loginSignup.sendChangeEmailOk.scala.html
第一階段,修改信箱資訊填寫正確後,寄信給使用者後,成功畫面提示。
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>寄送修改電子信箱</title>
@views.html.web.headerLibs()
@views.html.web.loginSignup.loginSignupLibs()
</head>
<body>
<div id="page-wrapper">
<div id="select_nav_user">@views.html.web.headerNav()</div>
</div>
<div class="form">
<ul class="tab-group">
<li class="tab active"><a href="#">寄送修改電子信箱</a></li>
</ul>
<div class="tab-content">
<div id="signup">
<span>修改註冊信箱信件已寄出,請到新信箱進行收取信件,進行後續認證動作,謝謝。</span>
</div>
</div><!-- tab-content -->
</div> <!-- /form -->
<div id="titleBar"></div>
</body>
</html>
app.views.web.loginSignup.authNewEmail.scala.html
第二階段,修改信箱,點選信件回來時的驗證頁面,使用這需要在這個頁面上,填寫信件內的驗證碼檢核。
@(token:String)
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>更換電子信箱</title>
@views.html.web.headerLibs()
@views.html.web.loginSignup.loginSignupLibs()
</head>
<body>
<div id="page-wrapper">
<div id="select_nav_user">@views.html.web.headerNav()</div>
</div>
<div class="form">
<ul class="tab-group">
<li class="tab active"><a>更換電子信箱</a></li>
</ul>
<div class="tab-content">
<div id="Form" >
<form action="@controllers.routes.WebController.doAuthNewEmail.url" method="post" id="doAuthNewEmailForm">
<div class="field-wrap">
<label class="lable-field-wrap">驗證碼</label>
<input type="text" required autocomplete="off" name="checkCode"/>
@if(flash.containsKey("error")) {
<span style="color:red;">@flash.get("error")</span>
}
</div>
<h5>PS:請輸入信件內的驗證碼,完成認證動作。</h5>
<input type="hidden" value="@token" name="token"/>
<a>
<input type="submit" value="SUBMIT" class="button button-block">
</a>
</form>
</div>
</div><!-- tab-content -->
</div> <!-- /form -->
<div id="titleBar"></div>
<script src='@routes.Assets.versioned("javascripts/loginSignup.js")'></script>
<script>
$( document ).ready(function() {
document.getElementById("setPasswordForm").reset();
});
</script>
</body>
</html>
app.views.web.loginSignup.changeEmailOk.scala.html
第二階段,修改信箱成功頁面。相關驗證正確後,會轉頁到信箱修改成功的頁面。
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>修改電子信箱成功</title>
@views.html.web.headerLibs()
@views.html.web.loginSignup.loginSignupLibs()
</head>
<body>
<div id="page-wrapper">
<div id="select_nav_user">@views.html.web.headerNav()</div>
</div>
<div class="form">
<ul class="tab-group">
<li class="tab active"><a href="#">修改電子信箱成功</a></li>
</ul>
<div class="tab-content">
<div id="signup">
<span>修改註冊信箱信件成功,請到回到首頁,重新登入,謝謝。</span>
</div>
</div><!-- tab-content -->
</div> <!-- /form -->
<div id="titleBar"></div>
</body>
</html>
app.views.web.headerNav.scala.html
上面Menu新增修改信箱功能連結。
@import utils.session.Utils_Session; var utilsSession = new Utils_Session();
<!-- Nav -->
<nav id="nav">
<ul>
<li id="nav_index"><a href="@controllers.routes.WebController.index.url">首頁</a></li>
<li id="nav_user">
<a>我的世界</a>
<ul>
<li><a href="@controllers.routes.WebController.login.url">登入</a></li>
@if(utilsSession.isClinetHaveCookie(request)){
<li><a href="@controllers.routes.WebController.editPassword.url">修改密碼</a></li>
<li><a href="@controllers.routes.WebController.editEmail.url">修改信箱</a></li>
}
<li><a href="@controllers.routes.WebController.logout.url">登出</a></li>
</ul>
</li>
<li id="nav_signup">
<a href="@controllers.routes.WebController.signup.url">註冊</a>
<ul>
<li><a href="@controllers.routes.WebController.resendAuthEmail.url">重發認證信</a></li>
<li><a href="@controllers.routes.WebController.forgotPassword.url">忘記密碼</a></li>
</ul>
</li>
</ul>
</nav>
...
app.controllers.WebController.java
相關的服務寫好之後,我們要開始寫實際的修改電子信箱流程,主要分成兩個階段。
第一個階段:填寫要修改的電子信箱,進行相關驗證後,寄送信件。
第二個階段:使用者點選修改信箱連結後,進行相關驗證後,進行修改信箱動作以及寄信。
...
import pojo.web.email.MemberChangeEmail;
import pojo.web.email.MemberSendChangeEmail;
...
/**
* <pre>
* Stage 1-1
*
* 取得修改信箱頁面
* 若有尚未修改信箱且尚未逾期,會顯示在畫面上
*
* Step 1 : 驗證是否是登入狀態中(AuthCheck)
* Step 2 : 抓取使用者memberNo
* Step 3 : 抓取使用者註冊信箱,尚未認證信箱
* Ok : 回傳結果到頁面
* </pre>
*/
@AuthCheck
public Result editEmail(){
// Step 2
String memberNo = new Utils_Session().getUserNo();
Logger.info("memberNo = " + memberNo);
if( memberNo == null || "".equals(memberNo) ){
flash().put("error", "系統忙碌中,請稍後再嘗試修改電子信箱,謝謝。0x2");
return ok(changeEmail.render(null));
}
// Step 3
MemberChangeEmail data = null;
try{
data = this.webService.getMemberEmails(memberNo);
} catch (Exception e){
e.printStackTrace();
return ok(changeEmail.render(null));
} finally {
if(data==null || data.getOriginalEmail()==null || "".equals(data.getOriginalEmail())){
flash().put("error", "讀取會員資料忙碌中,請稍後再嘗試,謝謝。0x3");
return ok(changeEmail.render(null));
}
}
Logger.info("data = " + Json.toJson(data));
return ok(changeEmail.render(data));
}
/**
* <pre>
* Stage 1-2
*
* Step 1 : 驗證是否是登入狀態中(AuthCheck)
* Step 2 : 驗證表單資料
* Step 3 : 信箱檢查是否註冊過或重覆
* Step 4 : 信箱檢查是否使用中
* OK 1 : 產生更換信箱相關資料
* Ok 2 : 寫入更換信箱表單
* Ok 3 : 寄送更換信箱認證碼信件
*</pre>
*/
@AuthCheck
public Result changeEmail(){
// Step 2
MemberChangeEmail data = null;
try{
data = formFactory.form(MemberChangeEmail.class).bindFromRequest().get();
} catch(Exception e){
e.printStackTrace();
} finally {
if(data==null){
flash().put("error", "系統忙碌中,請稍後再嘗試修改電子信箱,謝謝。0x4");
return ok(changeEmail.render(null));
}
}
// Step 3
if(data.getNewEmail()==null || "".equals(data.getNewEmail())){
flash().put("error", "請填入要修改的信箱,謝謝。0x5");
return ok(changeEmail.render(data));
}
// Step 4
boolean isExists = false;
Member member =null;
try{
isExists = this.webService.checkMemberByEmail(data.getNewEmail());
member = this.webService.findMemberByMemberNo(new Utils_Session().getUserNo());
} catch (Exception e){
e.printStackTrace();
flash().put("error", "系統忙碌中,請稍後再嘗試修改電子信箱,謝謝。0x6");
return ok(changeEmail.render(data));
}
if(isExists || data.getNewEmail().equals(member.getEmail())){
flash().put("error", "該電子信箱使用中,請更換其他電子信箱,謝謝。0x7");
return ok(changeEmail.render(data));
}
MemberSendChangeEmail sendData = null;
int isWriteOk = 0;
boolean isSendOk = false;
try {
// OK 1
String memberNo = new Utils_Session().getUserNo();
String oldEmail = data.getOriginalEmail();
String newEmail = data.getNewEmail();
sendData = new Utils_Signup().genMemberSendChangeEmail(memberNo, oldEmail, newEmail);
if(sendData==null){
flash().put("error", "產生修改信箱資料發生錯誤,請聯絡管理者,謝謝。0x8");
return ok(changeEmail.render(data));
}
// OK 2
isWriteOk = this.webService.genMemberSendChangeEmail(sendData);
if(isWriteOk==0){
flash().put("error", "產生寄信資料發生錯誤,請聯絡管理者,謝謝。0x9");
return ok(changeEmail.render(data));
}
// OK 3
Utils_Email utilsEmail = new Utils_Email();
String userName = this.webService.findMemberByMemberNo(memberNo).getUsername();
Email mail = utilsEmail.genMemberSendChangeEmailData(userName,sendData);
isSendOk = utilsEmail.sendMail(mail);
if(!isSendOk){
flash().put("error", "寄送更換信箱信件發生錯誤,請重新使用修改信箱功能,謝謝。0x10");
return ok(changeEmail.render(data));
}
} catch(Exception e) {
e.printStackTrace();
flash().put("error", "系統忙碌中,請稍後再嘗試修改電子信箱,謝謝。0x11");
return ok(changeEmail.render(data));
} finally {
Logger.info("isWriteOk = " + isWriteOk + " , isSendOk = " + isSendOk + " , sendData = " + (sendData!=null ? Json.toJson(sendData) : "轉換傳送信件格式錯誤"));
}
return ok(sendChangeEmailOk.render());
}
/**
* <pre>
* Stage 2-1
*
* 重設電子信箱信件寄送回來後
*
* Step 1 : 檢查電子信箱信件連結是否有資料
* Step 2 : 檢查Token,是否可以查詢到會員資料
* Step 3 : 檢查Token,是否使用過了
* Step 4 : 檢查Token,是否逾期了
* OK : 檢查通過,可以進行重設電子信箱動作,並把Token儲存在表單裡
* </pre>
*/
public Result authNewEmail(){
// 清除暫存錯誤訊息
flash().clear();
// Step 1
String token = "";
try{
token = request().getQueryString("token");
} catch (Exception e){
e.printStackTrace();
flash().put("error", "重設電子信箱連結有誤,請確認是否有點選正確,謝謝。0x1");
return ok(authNewEmail.render(""));
}
// Step 2
MemberSendChangeEmail data = null;
try{
data = webService.getMemberSendChangeEmailByToken(token);
} catch(Exception e){
e.printStackTrace();
flash().put("error", "系統忙碌中,請稍候再嘗試,謝謝。");
return ok(authNewEmail.render(""));
} finally {
if(data == null){
flash().put("error", "重設電子信箱連結有誤,請確認是否有點選正確,謝謝。0x2");
return ok(authNewEmail.render(""));
}
}
// Step 3
if(data.isUse()){
flash().put("error", "重設電子信箱連結已失效,請重新使用修改信箱功能,謝謝。0x3");
play.Logger.warn("memberToken = " + Json.toJson(data));
return ok(authNewEmail.render(""));
}
// Step 4
long dbTime = Long.parseLong(data.getDbTime()); // 資料庫時間
long expiryDate = Long.parseLong(data.getExpiryDate()); // 逾期時間
play.Logger.info("dbTime = " + dbTime + ", expiryDate = " + expiryDate);
if(dbTime > expiryDate){
flash().put("error", "重設電子信箱連結已經超過24小時,請重新使用修改信箱功能,謝謝。0x4");
return ok(authNewEmail.render(""));
}
// Ok
return ok(authNewEmail.render(token));
}
/**
* <pre>
* Stage 2-2
*
* 開始進行重設信子信箱
*
* Step 1 : 檢查電子信箱信件連結是否有資料
* Step 2 : 檢查Token,是否可以查詢到會員資料
* Step 3 : 檢查Token,是否使用過了
* Step 4 : 檢查Token,是否逾期了
* Step 5 : 驗證碼是否正確
*
* Ok 1 : 寫入會員修改資料紀錄
* Ok 2 : 會員的電子信箱進行更新
* Ok 3 : 會員修改電子信箱表單,更新成使用過
* Ok 4 : 寄信到新的電子信箱,已更新
*
* </pre>
*/
public Result doAuthNewEmail(){
// 清除暫存錯誤訊息
flash().clear();
// Step 1
String token = "";
try{
token = formFactory.form().bindFromRequest().get().getData().get("token").toString();
} catch (Exception e){
e.printStackTrace();
flash().put("error", "重設電子信箱連結有誤,請確認是否有點選正確,謝謝。0x1");
return ok(authNewEmail.render(""));
}
// Step 2
MemberSendChangeEmail data = null;
try{
data = webService.getMemberSendChangeEmailByToken(token);
} catch(Exception e){
e.printStackTrace();
flash().put("error", "系統忙碌中,請稍候再嘗試,謝謝。");
return ok(authNewEmail.render(""));
} finally {
if(data == null){
flash().put("error", "重設電子信箱連結有誤,請確認是否有點選正確,謝謝。0x2");
return ok(authNewEmail.render(""));
}
}
// Step 3
if(data.isUse()){
flash().put("error", "重設電子信箱連結已失效,請重新使用修改信箱功能,謝謝。0x3");
play.Logger.warn("memberToken = " + Json.toJson(data));
return ok(authNewEmail.render(""));
}
// Step 4
long dbTime = Long.parseLong(data.getDbTime()); // 資料庫時間
long expiryDate = Long.parseLong(data.getExpiryDate()); // 逾期時間
play.Logger.info("dbTime = " + dbTime + ", expiryDate = " + expiryDate);
if(dbTime > expiryDate){
flash().put("error", "重設電子信箱連結已經超過24小時,請重新使用修改信箱功能,謝謝。0x4");
return ok(authNewEmail.render(""));
}
// Step 5
String checkCode = "";
try{
checkCode = formFactory.form().bindFromRequest().get().getData().get("checkCode").toString();
} catch (Exception e){
e.printStackTrace();
flash().put("error", "系統忙碌中,請稍候再嘗試,謝謝。");
return ok(authNewEmail.render(""));
}
if(!data.getCheckCode().equals(checkCode)){
flash().put("error", "驗證碼輸入錯誤,請重新輸入,謝謝。0x5");
return ok(authNewEmail.render(token));
}
int isLogMemberOk = 0;
int isUpdateEmailOk = 0;
int isUpdateUseOk = 0;
boolean isSendOk = false;
try{
// Ok 1
Member beforeUpdatemember = this.webService.findMemberByMemberNo(data.getMemberNo());
isLogMemberOk = this.webService.genMemberChangeLog(beforeUpdatemember);
// Ok 2
String memberNo = data.getMemberNo();
String newEmail = data.getNewEmail();
isUpdateEmailOk = this.webService.updateMemberEmail(memberNo,newEmail);
if(isUpdateEmailOk==0){
flash().put("error", "更新會員資料發生錯誤,請聯絡管理者,謝謝。0x6");
return ok(authNewEmail.render(token));
}
// Ok 3
data.setUse(true);
isUpdateUseOk = this.webService.genMemberSendChangeEmail(data);
if(isUpdateUseOk==0){
flash().put("error", "更新會員資料發生錯誤,請聯絡管理者,謝謝。0x7");
return ok(authNewEmail.render(token));
}
// Ok 4
Utils_Email utilsEmail = new Utils_Email();
Member afterUpdateMember = this.webService.findMemberByMemberNo(memberNo);
Email mail = utilsEmail.genMemberChangeEmailOk(afterUpdateMember);
isSendOk = utilsEmail.sendMail(mail);
} catch (Exception e) {
e.printStackTrace();
} finally {
play.Logger.info("isLogMemberOk = " + isLogMemberOk + " , isUpdateEmailOk = " + isUpdateEmailOk +
" , isUpdateUseOk = " + isUpdateUseOk + " , isSendOk = " + isSendOk);
}
// Clear cookie
new Utils_Session().clearClientCookie(response());
return ok(changeEmailOk.render());
}
conf.routes
相關的程式都已經就位,我們最後要把相關的網站服務路徑,寫到routes上,確保我們的服務可以被呼叫到。
# http://127.0.0.1:9000/web/editEmail
GET /web/editEmail controllers.WebController.editEmail()
# http://127.0.0.1:9000/web/changeEmail
POST /web/changeEmail controllers.WebController.changeEmail()
# http://127.0.0.1:9000/web/authNewEmail
GET /web/authNewEmail controllers.WebController.authNewEmail()
# http://127.0.0.1:9000/web/doAuthNewEmail
POST /web/authNewEmail controllers.WebController.doAuthNewEmail()
[Stage 1-1 ~ 1-2 Test Case]
CASE 1 : 抓取使用者memberNo錯誤
CASE 2 : 抓取使用者註冊信箱,尚未認證信箱
CASE 3 :驗證表單資料失敗
CASE 4 : 信箱是否有填寫
CASE 5 : 信箱檢查是否使用中
CASE 6 : 產生修改信箱資料發生錯誤
CASE 7 : 產生寄信資料發生錯誤
CASE 8 : 寄送更換信箱信件發生錯誤
OK : 以上檢核成功,會成功寄出修改電子信箱信件,且轉到成功寄信頁面。這樣我們第一個階段,就算是完成了,接下來就是使用者,從信件點選修改電子信箱連結,進行後續驗證動作
[Test Case 2-1~2-2]
CASE 1 : 檢查電子信箱信件連結是否有資料
CASE 2 : 檢查Token,是否可以查詢到會員資料
CASE 3 : 檢查Token,是否使用過了
CASE 4 : 檢查Token,是否逾期了
CASE 5 : 驗證碼是否正確
CASE 6 : 更新會員信箱資料發生錯誤
CASE 7 : 更新會員修改電子信箱表單發生錯誤
OK :第二階段,以上都檢核完畢,會進行四個動作,1.寫入會員修改資料紀錄、2.更新會員的電子信箱、3.會員修改電子信箱表單,更新成使用過、4.寄信到新的電子信箱。提示使用者這些動作都完成之後,他的信箱就會成功更換成新的電子信箱。
[Final]
以上就是使用者進行更換電子信箱的相關流程與實作,下一個小節,我們將會讓使用者,填寫更完善詳細的會員資料。