信用卡 PRIME Mode 開發者文件
信用卡 PRIME Mode 串接
串接概要
- 載入SDK
- 設置 SDK
- 設置信用卡資料填寫欄位
- 自定義callback function 處理 Prime
- 使用 Prime 進行交易授權請求
事前準備
- 請向ACpay申請PRIME mode設定資訊
- 請向ACpay提供付款頁面所屬的網域網址
1. 載入SDK
載入ACpay最新SDK (2024/12 update v1.0.5)
測試區
<script src="https://connectjs.payloop.com.tw/ACconnect/v1.0.5.js" ></script>正式區
<script src="https://connectjs.acpay.com.tw/ACconnect/v1.0.5.js" ></script>2. 設置SDK
將申請之相關參數設置完成以使用SDK
<script>
ACconnect.setupSDK("appID", "appKey", "serverType");
</script>| 名稱(*=必填) | 類別 | 內容 |
|---|---|---|
| appID* | int | 驗證識別碼 |
| appKey* | String | 驗證金鑰 |
| serverType* | String | 使用的伺服器種類: – 測試時請使用 Sandbox 環境(sandbox) – 上線後請切換至 Production 環境 (production) |
3. 設置信用卡資料填寫欄位
ACconnect.card.setup({
fields: {
number: {
element: '.form-control.card-number',
placeholder: '**** **** **** ****'
},
expirationDate: {
element: document.getElementById('acpay-expiration-date'),
placeholder: 'MM / YY'
},
ccv: {
element: '.form-control.cvc',
placeholder: '安全碼'
}
},
styles: {
'input': {
'color': 'gray'
},
'input.ccv': {
'font-size': '16px'
},
':focus': {
'color': 'black'
},
'.valid': {
'color': 'green'
},
'.invalid': {
'color': 'red'
},
'@media screen and (max-width: 400px)': {
'input': {
'color': 'orange'
}
}
}
})4. 自定義 callback function 使用 Prime
依照店家使用需求取得 api 回傳 Prime並進行後續交易授權所需處理。
//Pass the callback function as an argument and you will get the prime string
ACconnect.card.getPrime(function (result) {
if (result.status !== 0) {
alert('get prime error ' + result.msg);
return
}
alert('get prime 成功,prime: ' + result.card.prime);
})5. 使用 Prime 進行交易授權請求
取得Prime 及當前交易資訊對ACpay進行交易授權請求。(詳細請見網路特店暨線上授權服務系統 付款服務使用手冊)
Example Code:
<!DOCTYPE html>
<html lang="en">
<head>
<title>PRIME Mode</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style>
body {
margin: 20px 0;
}
.jumbotron {
text-align: center;
}
.text-left {
text-align: left;
}
.container {
max-width: 750px;
}
form {
padding: 40px;
box-shadow: 0 7px 14px rgba(50, 50, 93, 0.1), 0 3px 6px rgba(0, 0, 0, 0.08);
}
.acpay-field-focus {
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
}
.has-error .acpay-field-focus {
border-color: #843534;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;
}
.has-success .acpay-field-focus {
border-color: #2b542c;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;
}
</style>
</head>
<body>
<div class="container">
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="Email">
</div>
<div class="form-group card-number-group">
<label for="card-number" class="control-label"><span id="cardtype"></span>卡號</label>
<div class="form-control card-number"></div>
</div>
<div class="form-group expiration-date-group">
<label for="expiration-date" class="control-label">卡片到期日</label>
<div class="form-control expiration-date" id="acpay-expiration-date"></div>
</div>
<div class="form-group cvc-group">
<label for="cvc" class="control-label">卡片後三碼</label>
<div class="form-control cvc"></div>
</div>
<button type="submit" class="btn btn-default">Pay</button>
</form>
<br>
<pre class="jumbotron text-left" id="curl">
</pre>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="https://connectjs.payloop.com.tw/ACconnect/v1.0.3.js"></script>
<script>
ACconnect.setupSDK('090414780201003', '854b72ab-3828-4994-ab6c-16b5145937a8', 'sandbox');
ACconnect.card.setup({
fields: {
number: {
element: '.form-control.card-number',
placeholder: '**** **** **** ****'
},
expirationDate: {
element: document.getElementById('acpay-expiration-date'),
placeholder: 'MM / YY'
},
ccv: {
element: '.form-control.cvc',
placeholder: '安全碼'
}
},
styles: {
'input': {
'color': 'gray'
},
'input.ccv': {
// 'font-size': '16px'
},
':focus': {
'color': 'black'
},
'.valid': {
'color': 'green'
},
'.invalid': {
'color': 'red'
},
'@media screen and (max-width: 400px)': {
'input': {
'color': 'orange'
}
}
}
})
// listen for ACconnect Field
ACconnect.card.onUpdate(function (update) {
console.log(update);
/* Disable / enable submit button depend on update.canGetPrime */
/* ============================================================ */
// update.canGetPrime === true
if (update.canGetPrime) {
$('button[type="submit"]').removeAttr('disabled');
} else {
$('button[type="submit"]').attr('disabled', true);
}
/* Change card type display when card type change */
/* ============================================== */
// cardTypes = ['visa', 'mastercard', ...]
var newType = update.cardType === 'unknown' ? '' : update.cardType;
$('#cardtype').text(newType);
/* Change form-group style when ACconnect field status change */
/* ======================================================= */
if (update.status.number === 2) {
setNumberFormGroupToError('.card-number-group');
} else if (update.status.number === 0) {
setNumberFormGroupToSuccess('.card-number-group');
} else {
setNumberFormGroupToNormal('.card-number-group');
}
if (update.status.expiry === 2) {
setNumberFormGroupToError('.expiration-date-group');
} else if (update.status.expiry === 0) {
setNumberFormGroupToSuccess('.expiration-date-group');
} else {
setNumberFormGroupToNormal('.expiration-date-group');
}
if (update.status.cvc === 2) {
setNumberFormGroupToError('.cvc-group');
} else if (update.status.cvc === 0) {
setNumberFormGroupToSuccess('.cvc-group');
} else {
setNumberFormGroupToNormal('.cvc-group');
}
})
function nonce() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
}
return s4() + s4() + s4() + s4() + s4() + s4() + s4() + s4();
}
$('form').on('submit', function (event) {
event.preventDefault();
// fix keyboard issue in iOS device
forceBlurIos();
console.log(event);
const accStatus = ACconnect.card.getACpayFieldsStatus();
console.log(accStatus);
if (accStatus.canGetPrime === false) {
alert('can not get prime');
return;
}
//Pass the callback function as an argument and you will get the prime string
ACconnect.card.getPrime(function (result) {
if (result.status !== 0) {
alert('get prime error ' + result.msg);
return;
}
alert('get prime 成功,prime: ' + result.card.prime);
})
})
function setNumberFormGroupToError(selector) {
$(selector).addClass('has-error');
$(selector).removeClass('has-success');
}
function setNumberFormGroupToSuccess(selector) {
$(selector).removeClass('has-error');
$(selector).addClass('has-success');
}
function setNumberFormGroupToNormal(selector) {
$(selector).removeClass('has-error');
$(selector).removeClass('has-success');
}
function forceBlurIos() {
if (!isIos()) {
return;
}
var input = document.createElement('input');
input.setAttribute('type', 'text');
// Insert to active element to ensure scroll lands somewhere relevant
document.activeElement.prepend(input);
input.focus();
input.parentNode.removeChild(input);
}
function isIos() {
return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
}
</script>
</body>
</html>