信用卡 PRIME Mode 開發者文件

信用卡 PRIME Mode 串接

串接概要
  1. 載入SDK
  2. 設置 SDK
  3. 設置信用卡資料填寫欄位
  4. 自定義callback function 處理 Prime
  5. 使用 Prime 進行交易授權請求
事前準備
  • 請向ACpay申請PRIME mode設定資訊
  • 請向ACpay提供付款頁面所屬的網域網址
1. 載入SDK

載入ACpay最新SDK (2023/08 update v1.0.3)

				
					<script src="https://connectjs.payloop.com.tw/ACconnect/v1.0.3.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('090453990201003', 'e509c975-679e-4040-9d82-f2e2de6227b1', '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>