NAV
php csharp java javascript python

經銷商 MYPAY LINK 直接交易

修改歷程

版本 異動日期 修訂內容 位置
1.0 2021.01.01 新版文件
1.0.1 2023.04.07 新增開發前請先閱讀 20230407_01
1.0.2 2023.07.26 新增特約商店可用支付工具 20230726_01

開發前請先閱讀

金鑰的注意事項

Q:金鑰的有效期限

A:MyPay的金鑰有效期限只有一年,如果要延長,請自行至金鑰管理系統延長

Q:金鑰可以在什麼時候延長

A:到期日7天前,都可以延長(不包含第7天),一但超過,系統自動產生新金鑰後,即不可再延長

Q:金鑰即將到期前7天時,系統新發的金鑰是否會於信件中夾帶

A:會

Q:金鑰在到期前何時會發信通知

A:定期發送金鑰到期通知的頻率為:60天/30天/20天,若 貴司皆無動作,則系統會於到期前七天產製新金鑰並發送email到 貴司技術窗口信箱,此時舊的金鑰,因還未過期還可以使用,一旦過期,貴司仍使用舊金鑰則會無法交易

交易結果的告知

Q:何時會給予交易結果

A:當mypay接收到交易的http request後,會立即回應交易結果於http response body,除此之外,MyPay也會由附錄三這邊的設定,背景主動發動通知商家

Q:當我接到MyPay通知時該做什麼

A:請直接回應8888,如沒有回應,MyPay會通知5次,若5次內均得不到8888,系統會寄發信件給予商家的技術人員以及附錄三而外設定的人員

行動支付測試

Q:那些行動支付工具可以做測試

A:目前除了line pay外,其餘行動支付,因上游無提供測試資料,皆無法進行測試

直接交易設計概要

安全性設計

所有的付費要求發動都僅能從經銷商的網頁伺服器發出請求,將傳輸的資料以AES加密,再透過HTTPS加密傳輸。交易資料不由消費者端送出,可確保資料不被消費者竄改。所有付費資訊經過MYPAY Link匝道進行轉送處理,經銷商不需要處理消費者的付費流程以及安全控管。

資料驗證

交易參數中有一組由雜湊函式運算出的驗証碼,作為資料驗証用,以確保資料正確性。 大部分交易模式,經銷商以導頁的方式處理付費流程,經銷商只需確保與MYPAY LINK連線正常,即可確保交易安全以及確保資料安全。

系統架構

所有的交易請求與查詢只能透過伺服器發動,由經銷商的網頁伺服器利用伺服端服務程式發動交易,以避免交易資料被消費者竄改或攔截。為確保交易安全,MYPAY Link僅能接受 https connection,注意僅接受TLS1.2以上協定。

MYPAY LINK 目前提供之服務與格式

MYPAY LINK 提供多種交易與應用方式,應用情境如下:

(1)虛擬帳號交易請求:產生一組虛擬帳號,可透過ATM轉帳。

(2)超商代碼交易請求:產生ibon、FamiPort、Hi-Life等繳費代碼或繳費條碼自行產生條碼後供超商掃碼繳費。

(3)WebATM交易請求:產生指定金額之導頁網頁資料到銀行WebATM做交易。

(30)後付款交易請求:提交消費者與出貨資訊給後付款。

(31)後付款請款請求:提交貨運資訊給後付款確認請款。

(32)後付款更正出貨請求:未請款前,更正出貨的資訊。

(33)後付款查詢出貨請求:查詢後付款出貨相關資訊。

(34)電票交易請求:發動電子票證交易,消費者透過感應卡機進行付款消費。

(35)電票查詢卡號請求:查詢電子票證之卡號資訊。

(36)電票查詢餘額請求:查詢電子票證餘額。

(37)電票退款請求:發動電子票證交易之退款,消費者透過感應卡機退回電子票證。

(38)eACH交易請求:當消費者申請eDDA電子化授權核印通過後,可發動此交易請求做交易動作。

(39)超商條碼繳費:消費至超商或繳費單位使用條碼繳費。

(40)全支付線上交易請求:商家串接MyPay,直接取得付款網址或開啟APP。

(41)全支付線下交易請求:消費者提供PXPay plus支付碼供設備進行掃碼做交易動作。

(42)LINE Pay線上交易請求:商家串接MyPay,直接取得付款網址或開啟APP。

(43)LINE Pay線下交易請求:消費者提供LINE Pay支付碼供設備進行掃碼做交易動作。

(44)Pi線上交易請求:商家串接MyPay,直接取得付款網址或開啟APP。

(45)Pi線下交易請求:消費者提供Pi支付碼供設備進行掃碼做交易動作。

(46)微信線下交易請求:消費者提供微信支付碼供設備進行掃碼做交易動作。

(47)街口線下交易請求:商家串接MyPay,直接取得付款網址或開啟APP。

(48)街口線下交易請求:消費者提供街口支付碼供設備進行掃碼做交易動作。

(49)Apple Pay線下交易請求:消費者提供Apple Pay支付碼供設備進行掃碼做交易動作。

(50)Google Pay線下交易請求:消費者提供Google Pay支付碼供設備進行掃碼做交易動作。

(51)悠遊付線下交易請求:消費者提供悠遊付支付碼供設備進行掃碼做交易動作。

(52)支付寶線下交易請求:消費者提供支付寶支付碼供設備進行掃碼做交易動作。

(53)自行收款交易請求:商店自行向消費者收款時,可發動此交易請求,將收款記錄在MYPAY

(54)直接交易查詢:向系統發動,若未接收到交易結果回報,可透過此方法確認交易狀況。

(55)交易退款:金流交易退款,支援即時退款且未超過退款期限內之支付方式皆可使用此方式發動退款。

(56)全盈支付線上交易請求:商家串接MyPay,直接取得付款網址或開啟APP。

(57)全盈支付線下交易請求:消費者提供全盈支付碼供設備進行掃碼做交易動作。

我們提供介接方式是透過https連線,只接受POST方式傳送交易資料。

介接網址

經銷商模式

位置 API介接網址
測試區 https://pay.usecase.cc/api/agent
正式區 https://ka.mypay.tw/api/agent

Client模式(限定功能)

位置 API介接網址
測試區 https://pay.usecase.cc/api/open
正式區 https://ka.mypay.tw/api/open

資料加密方式

AES 256編碼 + base64編碼(附錄四資料加密方式)

加密金鑰

金鑰會透過mail發送,也可從管理後台取得

文字編碼

一律使用UTF-8相容編碼

虛擬帳號交易

<?php
/**
 * 經銷商串接-直接交易-虛擬帳號
 */
final class AgentECollection
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "E_COLLECTION";
        $rawData['limit_pay_days'] = 7;
        $rawData['supplier_code'] = "B2";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentECollection = new AgentECollection();
$AgentECollection->run();
?>
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-虛擬帳號
    /// </summary>
    public class AgentECollection {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentECollection simulator = new AgentECollection();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";

            items.Add(item);

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost = "10";
            rawData.user_id = "phper";
            rawData.order_id = "1234567890";
            rawData.ip = "127.0.0.1"; // 此為消費者IP,會做為驗證用
            rawData.pfn = "E_COLLECTION";
            rawData.limit_pay_days = "7";
            rawData.supplier_code = "B2";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-虛擬帳號
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentECollection {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentECollection simulator = new AgentECollection();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", "10");
        rawData.put("user_id", "phper");
        rawData.put("order_id", "1234567890");
        rawData.put("ip", "127.0.0.1"); // 此為消費者IP,會做為驗證用
        rawData.put("pfn", "E_COLLECTION");
        rawData.put("limit_pay_days", "7");
        rawData.put("supplier_code", "B2");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-虛擬帳號
 */
function AgentECollection() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentECollection.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [{
            'id': "1",
            'name': "商品名稱",
            'cost': "10",
            'amount': "1",
            'total': "10"
        }],
        cost: "10",
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "E_COLLECTION",
        limit_pay_days: 7,
        supplier_code: "B2"
    };
};
/**
 * 取得服務位置
 */
AgentECollection.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentECollection.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentECollection.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentECollection.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentECollection.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentECollection = new AgentECollection();
AgentECollection.run();

import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-超商代碼
"""
class AgentCStoreCode:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [{
                'id': "1",
                'name': "商品名稱",
                'cost': "10",
                'amount': "1",
                'total': "10"
            }],
            'cost': "10",
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "CSTORECODE",
            'limit_pay_days': "3",
            'supplier_code': "S0"
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentCStoreCode = AgentCStoreCode()
AgentCStoreCode.run()

回傳 JSON 結構如下:

{
    "code": "270",
    "msg": "執行成功。",
    "uid": 75568,
    "key": "3bb205d8f2c315d073fc62c5de8d9761",
    "finishtime": "",
    "cardno": "",
    "acode": "",
    "order_id": "1234567890",
    "user_id": "phper",
    "cost": 10,
    "currency": "TWD",
    "actual_cost": 0,
    "actual_currency": "TWD",
    "pfn": "E_COLLECTION",
    "trans_type": 1,
    "result_type": 4,
    "result_content": "{\n    \"PinCode\": \"1255100349000018\",\n    \"LimitDate\": \"20201214113117\",\n    \"BankCode\": \"006\"\n}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": ""
}

發動交易後,得到一組銀行代號與繳費帳號,讓消費者透過ATM或臨櫃作繳費動作。

經銷商『虛擬帳號交易』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『虛擬帳號交易』欄位參考
JSON格式,AES256加密資料

『虛擬帳號交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 必填
『付款方式』值參考
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_address string(255) 消費者帳單地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type string 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
supplier_code string 金融供應商代碼(依合約設定之支援金融供應商) 必填
『金流供應商代碼』值參考
limit_pay_days string 繳費有效天數(如無此資料以系統設定為預設)

『虛擬帳號』回傳欄位

參數名稱 型態 說明 必須
code string 交易回傳碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content string(1000) 回傳結果 『虛擬帳號回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5

超商代碼交易

<?php
/**
 * 經銷商串接-直接交易-超商代碼
 */
final class AgentCStoreCode
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "CSTORECODE";
        $rawData['limit_pay_days'] = 3;
        $rawData['supplier_code'] = "S0";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentCStoreCode = new AgentCStoreCode();
$AgentCStoreCode->run();
?>
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-虛擬帳號
    /// </summary>
    public class AgentCStoreCode {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentCStoreCode simulator = new AgentCStoreCode();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";

            items.Add(item);

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost = "10";
            rawData.user_id = "phper";
            rawData.order_id = "1234567890";
            rawData.ip = "127.0.0.1"; // 此為消費者IP,會做為驗證用
            rawData.pfn = "CSTORECODE";
            rawData.limit_pay_days = "3";
            rawData.supplier_code = "S0";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-超商代碼
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentCStoreCode {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentCStoreCode simulator = new AgentCStoreCode();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", "10");
        rawData.put("user_id", "phper");
        rawData.put("order_id", "1234567890");
        rawData.put("ip", "127.0.0.1"); // 此為消費者IP,會做為驗證用
        rawData.put("pfn", "CSTORECODE");
        rawData.put("limit_pay_days", "3");
        rawData.put("supplier_code", "S0");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-超商代碼
 */
function AgentCStoreCode() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentCStoreCode.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [{
            'id': "1",
            'name': "商品名稱",
            'cost': "10",
            'amount': "1",
            'total': "10"
        }],
        cost: "10",
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "CSTORECODE",
        limit_pay_days: "3",
        supplier_code: "S0"
    };
};
/**
 * 取得服務位置
 */
AgentCStoreCode.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentCStoreCode.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentCStoreCode.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentCStoreCode.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentCStoreCode.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentCStoreCode = new AgentCStoreCode();
AgentCStoreCode.run();

import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-虛擬帳號
"""
class AgentECollection:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [{
                'id': "1",
                'name': "商品名稱",
                'cost': "10",
                'amount': "1",
                'total': "10"
            }],
            'cost': "10",
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "E_COLLECTION",
            'limit_pay_days': 7,
            'supplier_code': "B2"
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentECollection = AgentECollection()
AgentECollection.run()

回傳 JSON 結構如下:

{
    "code": "260",
    "msg": "執行成功。",
    "uid": 75569,
    "key": "0696b3e97553b8b2d4bdd845e2663aec",
    "finishtime": "",
    "cardno": "",
    "acode": "",
    "order_id": "1234567890",
    "user_id": "phper",
    "cost": 10,
    "currency": "TWD",
    "actual_cost": 0,
    "actual_currency": "TWD",
    "pfn": "CSTORECODE",
    "trans_type": 1,
    "result_type": 4,
    "result_content": "{\n    \"PinCode\": \"201231V0000156\",\n    \"BarCode1\": \"091207KK1\",\n    \"BarCode2\": \"00201231V0000156\",\n    \"BarCode3\": \"114332000000010\",\n    \"LimitDate\": \"20201210113252\"\n}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": ""
}

發動交易後,會依超商不同而得到不同的繳費代碼或繳費條碼。依規格產生相關的Qrcode或Barcode,提供消費者至超商作掃碼繳費動作。

經銷商『超商代碼交易』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『超商代碼交易』欄位參考
JSON格式,AES256加密資料

『超商代碼交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 必填
『付款方式』值參考
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
(如supplier_code = T2,此欄位有填,黑貓Pay發出E-Mail會有此資訊)
user_zipcode string(10) 消費者郵遞區號
(如supplier_code = T2,此欄位有填,黑貓Pay發出E-Mail會有此資訊)
user_address string(255) 消費者地址
(如supplier_code = T2,此欄位有填,黑貓Pay發出E-Mail會有此資訊)
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
(如supplier_code = T2,此欄位有填,會由黑貓Pay發出簡訊通知。註:測試環境黑貓Pay也可能會發送簡訊,勿隨意填)
user_email string(80) 消費者 E-Mail
(如supplier_code = T2,此欄位有填,則會由黑貓Pay發出E-Mail通知到這裡)
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type string 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
supplier_code string 金融供應商代碼(依合約設定之支援金融供應商) 必填
『金流供應商代碼』值參考
limit_pay_days string 繳費有效天數(如無此資料以系統設定為預設),FamiPort有限定3日內

『超商代碼交易』回傳欄位

參數名稱 型態 說明 必須
code string 交易回傳碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content string(1000) 回傳結果 『ibon』值參考
『FamiPort』值參考
『Hi Life』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5

WebATM交易

<?php
/**
 * 經銷商串接-直接交易-WebATM
 */
final class AgentWebATM
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "WEBATM";
        $rawData['supplier_code'] = "B2";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentWebATM = new AgentWebATM();
$AgentWebATM->run();
?>
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-WebATM
    /// </summary>
    public class AgentWebATM {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentWebATM simulator = new AgentWebATM();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";

            items.Add(item);

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost = "10";
            rawData.user_id = "phper";
            rawData.order_id = "1234567890";
            rawData.ip = "127.0.0.1"; // 此為消費者IP,會做為驗證用
            rawData.pfn = "WEBATM";
            rawData.supplier_code = "B2";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-WebATM
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentWebATM {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentWebATM simulator = new AgentWebATM();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", "10");
        rawData.put("user_id", "phper");
        rawData.put("order_id", "1234567890");
        rawData.put("ip", "127.0.0.1"); // 此為消費者IP,會做為驗證用
        rawData.put("pfn", "WEBATM");
        rawData.put("supplier_code", "B2");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-WebATM
 */
function AgentWebATM() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentWebATM.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [{
            'id': "1",
            'name': "商品名稱",
            'cost': "10",
            'amount': "1",
            'total': "10"
        }],
        cost: "10",
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "WEBATM",
        supplier_code: "B2"
    };
};
/**
 * 取得服務位置
 */
AgentWebATM.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentWebATM.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentWebATM.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentWebATM.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentWebATM.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentWebATM = new AgentWebATM();
AgentWebATM.run();

import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-WebATM
"""
class AgentWebATM:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [{
                'id': "1",
                'name': "商品名稱",
                'cost': "10",
                'amount': "1",
                'total': "10"
            }],
            'cost': "10",
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "WEBATM",
            'supplier_code': "B2"
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentWebATM = AgentWebATM()
AgentWebATM.run()

回傳 JSON 結構如下:

{
    "code": "280",
    "msg": "執行成功。",
    "uid": 75570,
    "key": "e79ddd457c540d12b8b09cd7790cf614",
    "finishtime": "",
    "cardno": "",
    "acode": "",
    "order_id": "1234567890",
    "user_id": "phper",
    "cost": 10,
    "currency": "TWD",
    "actual_cost": 0,
    "actual_currency": "TWD",
    "pfn": "WEBATM",
    "trans_type": 1,
    "result_type": 2,
    "result_content": "<!DOCTYPE html>\r\n<html>\r\n<form action='http:\/\/eatms.tcb-bank.com.tw\/fShop' method='POST' id='form1' name='form1' >\r\n<input type='hidden' name='CardBillRq' value='PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iYmlnNSI\/Pg0KPENhcmRCaWxsUnEgeG1sbnM6eHNkPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSI+DQogIDxTZW5kU2VxTm8+MjAyMDEyMDcxMDAwMDAwNzU1NzA8L1NlbmRTZXFObz4NCiAgPFR4VHlwZT4yNTYwPC9UeFR5cGU+DQogIDxQQVlOTz4wMDYyODkxNTE4ODUzMDE8L1BBWU5PPg0KICA8UGF5VHlwZT41OTk5OTwvUGF5VHlwZT4NCiAgPFVzZXJEYXRhPj8\/Pz88L1VzZXJEYXRhPg0KICA8T05PPjc1NTcwPC9PTk8+DQogIDxBY2N0SWRUbz4xMjU1MTAwMzQ1MDAwMDE2PC9BY2N0SWRUbz4NCiAgPEN1ckFtdD4xMDwvQ3VyQW10Pg0KICA8UGF5RHQ+MjAyMDEyMTA8L1BheUR0Pg0KICA8TUFDPmw0MlVaL3EwUkg1M0l5a21kczJGb1lGRG01eXJ4a3pCPC9NQUM+DQogIDxSc1VSTD5odHRwczovL3Rndy5teXBheS50dy9hcGkvd2ViYXRtL0V4dGVybmFsVGNiQ2xvc2VDYXNlPC9Sc1VSTD4NCjwvQ2FyZEJpbGxScT4='><!-- 帳號-->\r\n<input id='sub' type='submit' value='submit' style='display:none' \/>\r\n<script>\r\n  document.getElementById('sub').click();\r\n<\/script>\r\n<\/form>\r\n<\/html>\r\n",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": ""
}

當發動交易後,會得到一個轉址網頁資訊,透過網頁導頁方式,將消費者操作頁面導頁到銀行WebATM做交易。

經銷商『WebATM交易』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『WebATM交易』欄位參考
JSON格式,AES256加密資料

『WEBATM交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 必填
『付款方式』值參考
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_address string(255) 消費者帳單地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type string 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
supplier_code string 金融供應商代碼(依合約設定之支援金融供應商) 必填
『金流供應商代碼』值參考
success_returl string(255) 交易成功導頁網址
failure_returl string(255) 交易失敗導頁網址

『WEBATM交易』回傳欄位

參數名稱 型態 說明 必須
code string 交易回傳碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content string(1000) 回傳結果
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5

後付款交易

<?php
/**
 * 經銷商串接-直接交易-後付款
 */
final class AgentAfp
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '1000',
            'amount' => '1',
            'total' => '1000']];
        $rawData['cost'] = 1000;
        $rawData['user_id'] = "phper";
        $rawData['user_real_name'] = "金城武";
        $rawData['user_zipcode'] = "407";
        $rawData['user_address'] = "台中市西屯區市政路402號5樓之1";
        $rawData['user_cellphone'] = "0900000123";
        $rawData['user_email'] = "[email protected]";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "AFP";
        $rawData['shipping_info'] = ['shipment_type' => 2,
            'name' => "金城武",
            'tel' => '0900000123',
            'zip_code' => '432',
            'ship_address' => '台中市大肚區磺溪里15號'];

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentAfp = new AgentAfp();
$AgentAfp->run();
?>
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-後付款
    /// </summary>
    public class AgentAfp {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentAfp simulator = new AgentAfp();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "1000";
            item.amount = "1";
            item.total = "1000";

            items.Add(item);

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost = "1000";
            rawData.user_id = "phper";
            rawData.user_real_name = "金城武";
            rawData.user_zipcode = "407";
            rawData.user_address = "台中市西屯區市政路402號5樓之1";
            rawData.user_cellphone = "0900000123";
            rawData.user_email = "[email protected]";
            rawData.order_id = "1234567890";
            rawData.ip = "127.0.0.1"; // 此為消費者IP,會做為驗證用
            rawData.pfn = "AFP";

            dynamic info = new ExpandoObject();
            info.shipment_type = "2";
            info.name = "金城武";
            info.tel = "0900000123";
            info.zip_code = "432";
            info.ship_address = "台中市大肚區磺溪里15號";

            rawData.shipping_info = info;

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-後付款
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentAfp {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentAfp simulator = new AgentAfp();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "1000");
        item.put("amount", "1");
        item.put("total", "1000");
        items.add(item);

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", "1000");
        rawData.put("user_id", "phper");
        rawData.put("user_real_name", "金城武");
        rawData.put("user_zipcode", "407");
        rawData.put("user_address", "台中市西屯區市政路402號5樓之1");
        rawData.put("user_cellphone", "0900000123");
        rawData.put("user_email", "[email protected]");
        rawData.put("order_id", "1234567890");
        rawData.put("ip", "127.0.0.1"); // 此為消費者IP,會做為驗證用
        rawData.put("pfn", "AFP");

        Map<Object, Object> info = new HashMap<Object, Object>();
        info.put("shipment_type", "2");
        info.put("name", "金城武");
        info.put("tel", "0900000123");
        info.put("zip_code", "432");
        info.put("ship_address", "台中市大肚區磺溪里15號");

        rawData.put("shipping_info", info);

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}
const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-後付款
 */
function AgentAfp() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentAfp.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [{
            'id': "1",
            'name': "商品名稱",
            'cost': "1000",
            'amount': "1",
            'total': "1000"
        }],
        cost: "1000",
        user_id: "phper",
        user_real_name: "金城武",
        user_zipcode: "407",
        user_address: "台中市西屯區市政路402號5樓之1",
        user_cellphone: "0900000123",
        user_email: "[email protected]",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "AFP",
        shipping_info : {'shipment_type': 2,
                        'name': "金城武",
                        'tel': '0900000123',
                        'zip_code': '432',
                        'ship_address': '台中市大肚區磺溪里15號'
                    }
        };
};
/**
 * 取得服務位置
 */
AgentAfp.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentAfp.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentAfp.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentAfp.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentAfp.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentAfp = new AgentAfp();
AgentAfp.run();
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-後付款
"""
class AgentAfp:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [{
                'id': "1",
                'name': "商品名稱",
                'cost': "1000",
                'amount': "1",
                'total': "1000"
            }],
            'cost': "1000",
            'user_id': "phper",
            'user_real_name': "金城武",
            'user_zipcode': "407",
            'user_address': "台中市西屯區市政路402號5樓之1",
            'user_cellphone': "0900000123",
            'user_email': "[email protected]",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "AFP",
            'shipping_info': {
                'shipment_type': "2",
                'name': "金城武",
                'tel': "0900000123",
                'zip_code': "432",
                'ship_address': '台中市大肚區磺溪里15號'
            }
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentAfp = AgentAfp()
AgentAfp.run()

回傳 JSON 結構如下:

{
    "code": "284",
    "msg": "執行成功。線上訂單成立待出貨-未付款",
    "uid": 80998,
    "key": "2b4a8cef072c2b8a0b0805d54f54275f",
    "finishtime": "",
    "cardno": "",
    "acode": "",
    "order_id": "1234567890",
    "user_id": "phper",
    "cost": 1000,
    "currency": "TWD",
    "actual_cost": 0,
    "actual_currency": "TWD",
    "pfn": "AFP",
    "trans_type": 1,
    "result_type": 4,
    "result_content": "{\n    \"OrderTotalCost\": \"1000\",\n    \"TradeNo\": \"OD2100070580\",\n    \"TradeDate\": \"20210225173152\"\n}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": ""
}

「先擁有,後付款」網路購物新態度! 消費者收到繳費通知,九天內至全省四大超商、ATM繳費,消費者確認繳費資訊,再進行繳費。

經銷商『後付款交易』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『後付款交易』欄位參考
JSON格式,AES256加密資料

『後付款交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 『付款方式』值參考
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名 必填
user_zipcode string(10) 消費者郵遞區號 必填
user_address string(255) 消費者地址 必填
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話 必填
user_email string(80) 消費者 E-Mail 必填
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type string 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
shipping_info object 送貨資訊 必填
『後付款送貨資訊』欄位參考

『後付款』回傳欄位

參數名稱 型態 說明 必須
code string 交易回傳碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content string(1000) 回傳結果 『後付款交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5

後付款請款

<?php
/**
 * 經銷商串接-直接交易-後付款請款
 */
final class AgentAfpShipment
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['uid'] = "80747";
        $rawData['key'] = "42e46576add74966278a81faf53f732f";
        $rawData['shipment_no'] = "9876543210";
        $rawData['delivery_code'] = "1";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/afpshipment'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentAfpShipment = new AgentAfpShipment();
$AgentAfpShipment->run();
?>
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-後付款請款
    /// </summary>
    public class AgentAfpShipment {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentAfpShipment simulator = new AgentAfpShipment();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.uid = "80747";
            rawData.key = "42e46576add74966278a81faf53f732f";
            rawData.shipment_no = "9876543210";
            rawData.delivery_code = "1";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/afpshipment";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-後付款請款
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentAfpShipment {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentAfpShipment simulator = new AgentAfpShipment();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("uid", "80747");
        rawData.put("key", "42e46576add74966278a81faf53f732f");
        rawData.put("shipment_no", "9876543210");
        rawData.put("delivery_code", "1");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/afpshipment");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}
const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-後付款請款
 */
function AgentAfpShipment() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentAfpShipment.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        uid: "80747",
        key: "42e46576add74966278a81faf53f732f",
        shipment_no: "9876543210",
        delivery_code: "1"
    };
};
/**
 * 取得服務位置
 */
AgentAfpShipment.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/afpshipment"
    };
};
/**
 * AES 256 加密
 */
AgentAfpShipment.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentAfpShipment.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentAfpShipment.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentAfpShipment.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentAfpShipment = new AgentAfpShipment();
AgentAfpShipment.run();
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-後付款請款
"""
class AgentAfpShipment:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'uid': "80747",
            'key': "42e46576add74966278a81faf53f732f",
            'shipment_no': "9876543210",
            'delivery_code': "1"
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/afpshipment'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentAfpShipment = AgentAfpShipment()
AgentAfpShipment.run()

回傳 JSON 結構如下:

{
    "code": "250",
    "msg": "執行成功。",
    "uid": 80998,
    "key": "2b4a8cef072c2b8a0b0805d54f54275f",
    "finishtime": "20210225173326",
    "cardno": "OD2100070580",
    "acode": "",
    "order_id": "1234567890",
    "user_id": "phper",
    "cost": 1000,
    "currency": "TWD",
    "actual_cost": 0,
    "actual_currency": "TWD",
    "pfn": "AFP",
    "trans_type": 1,
    "result_type": 4,
    "result_content": "{\n    \"OrderTotalCost\": 1000,\n    \"TradeDate\": \"20210225173326\",\n    \"TradeNo\": \"OD2100070580\"\n}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": ""
}

發動後付款交易後,特約商店確認已經出貨給消費者後,即可以發動請款請求。

經銷商『後付款請款』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/afpshipment"}
JSON格式,AES256加密資料
encry_data text 『後付款請款』欄位參考
JSON格式,AES256加密資料

『後付款請款』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼
key string 特約商店驗證碼
uid string 訂單編號(UID)
shipment_no string 出貨編號
delivery_code integer 貨運商家編號 『貨運商家編號』值參考

『後付款請款』回傳欄位

參數名稱 型態 說明 必須
code string 交易回傳碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content string(1000) 回傳結果 『後付款請款交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5

後付款更正出貨

<?php
/**
 * 經銷商串接-直接交易-後付款更正出貨
 */
final class AgentAfpShipmentUpdate
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['uid'] = "80747";
        $rawData['key'] = "42e46576add74966278a81faf53f732f";

        $rawData['shipping_info'] = ['shipment_type' => 2,
                                    'name' => "金城武",
                                    'tel' => '0900000123',
                                    'zip_code' => '432',
                                    'ship_address' => '台中市大肚區磺溪里16號'];

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/afpshipmentupdate'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentAfpShipmentUpdate = new AgentAfpShipmentUpdate();
$AgentAfpShipmentUpdate->run();
?>
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-後付款更正出貨
    /// </summary>
    public class AgentAfp {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentAfp simulator = new AgentAfp();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.uid = "80747";
            rawData.key = "42e46576add74966278a81faf53f732f";

            dynamic info = new ExpandoObject();
            info.shipment_type = "2";
            info.name = "金城武";
            info.tel = "0900000123";
            info.zip_code = "432";
            info.ship_address = "台中市大肚區磺溪里16號";

            rawData.shipping_info = info;

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/afpshipmentupdate";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-後付款更正出貨
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentAfpShipmentUpdate {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentAfpShipmentUpdate simulator = new AgentAfpShipmentUpdate();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("uid", "80747");
        rawData.put("key", "42e46576add74966278a81faf53f732f");

        Map<Object, Object> info = new HashMap<Object, Object>();
        info.put("shipment_type", "2");
        info.put("name", "金城武");
        info.put("tel", "0900000123");
        info.put("zip_code", "432");
        info.put("ship_address", "台中市大肚區磺溪里16號");

        rawData.put("shipping_info", info);

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/afpshipmentupdate");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}
const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-後付款更正出貨
 */
function AgentAfpShipmentUpdate() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentAfpShipmentUpdate.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        uid: "80747",
        key: "42e46576add74966278a81faf53f732f",
        shipping_info: {
            shipment_type: "2",
            name: "金城武",
            tel: "0900000123",
            zip_code: "432",
            ship_address: "台中市大肚區磺溪里16號"
        }
    };
};
/**
 * 取得服務位置
 */
AgentAfpShipmentUpdate.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/afpshipmentupdate"
    };
};
/**
 * AES 256 加密
 */
AgentAfpShipmentUpdate.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentAfpShipmentUpdate.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentAfpShipmentUpdate.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentAfpShipmentUpdate.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentAfpShipmentUpdate = new AgentAfpShipmentUpdate();
AgentAfpShipmentUpdate.run();
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-後付款更正出貨
"""
class AgentAfpShipmentUpdate:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'uid': "80747",
            'key': "42e46576add74966278a81faf53f732f",
            'shipping_info': {
                'shipment_type': "2",
                'name': "金城武",
                'tel': "0900000123",
                'zip_code': "432",
                'ship_address': "台中市大肚區磺溪里16號"
            }
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/afpshipmentupdate'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentAfpShipmentUpdate = AgentAfpShipmentUpdate()
AgentAfpShipmentUpdate.run()

回傳 JSON 結構如下:

{
    "code": "B200",
    "msg": "執行成功"
}

發動後付款交易後,在後付款請款發動之前,如出貨資訊資訊不正確,可以發動更正出貨修正出貨資訊。

經銷商『後付款更正出貨』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/afpshipmentupdate"}
JSON格式,AES256加密資料
encry_data text 『後付款更正出貨』欄位參考
JSON格式,AES256加密資料

『後付款更正出貨』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼
key string 特約商店驗證碼
uid string 訂單編號(UID)
shipping_info object 送貨資訊 (後付款為必填) 『後付款送貨資訊』欄位參考

『後付款更正出貨』回傳欄位

參數名稱 型態 說明 必須
code string 回傳碼
msg string(500) 回傳訊息

後付款查詢出貨

<?php
/**
 * 經銷商串接-直接交易-後付款查詢出貨
 */
final class AgentAfpShipmentQuery
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['uid'] = "80685";
        $rawData['key'] = "35aeb13990e4d57c3735467498e51b6f";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/afpshipmentquery'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentAfpShipmentQuery = new AgentAfpShipmentQuery();
$AgentAfpShipmentQuery->run();
?>
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-後付款查詢出貨
    /// </summary>
    public class AgentAfpShipmentQuery {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentAfpShipmentQuery simulator = new AgentAfpShipmentQuery();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.uid = "80747";
            rawData.key = "42e46576add74966278a81faf53f732f";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/afpshipmentquery";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-後付款查詢出貨
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentAfpShipmentQuery {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentAfpShipmentQuery simulator = new AgentAfpShipmentQuery();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("uid", "80747");
        rawData.put("key", "42e46576add74966278a81faf53f732f");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/afpshipmentquery");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}
const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-後付款查詢出貨
 */
function AgentAfpShipmentQuery() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentAfpShipmentQuery.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        uid: "80747",
        key: "42e46576add74966278a81faf53f732f"
    };
};
/**
 * 取得服務位置
 */
AgentAfpShipmentQuery.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/afpshipmentquery"
    };
};
/**
 * AES 256 加密
 */
AgentAfpShipmentQuery.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentAfpShipmentQuery.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentAfpShipmentQuery.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentAfpShipmentQuery.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentAfpShipmentQuery = new AgentAfpShipmentQuery();
AgentAfpShipmentQuery.run();
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-後付款查詢出貨
"""
class AgentAfpShipmentQuery:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'uid': "80747",
            'key': "42e46576add74966278a81faf53f732f"
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/afpshipmentquery'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentAfpShipmentQuery = AgentAfpShipmentQuery()
AgentAfpShipmentQuery.run()

回傳 JSON 結構如下:

{
    "uid": 80998,
    "key": "2b4a8cef072c2b8a0b0805d54f54275f",
    "code": "250",
    "msg": "付款完成",
    "finishtime": "20210225173326",
    "trade_no": "OD2100070580",
    "order_id": "1234567890",
    "user_id": "phper",
    "user_real_name": "金城武",
    "user_zipcode": "407",
    "user_address": "台中市西屯區市政路402號5樓之1",
    "user_cellphone": "0900000123",
    "user_email": "[email protected]",
    "shipping_info": {
        "shipment_type": 2,
        "company_name": null,
        "department_name": null,
        "name": "金城武",
        "cvs": 0,
        "cvs_store": null,
        "cvs_store_name": null,
        "zip_code": "432",
        "ship_address": "台中市大肚區磺溪里15號",
        "tel": "0900000123"
    },
    "shipment_no": "9876543210",
    "delivery_code": 1,
    "cost": 1000,
    "currency": "TWD",
    "actual_cost": 1000,
    "actual_currency": "TWD",
    "pfn": "AFP",
    "refund_order": [],
    "invoice_state": 0,
    "invoice_date": "",
    "invoice_wordtrack": "",
    "invoice_number": "",
    "invoice_rand_code": "",
    "invoice_seller_ban": "",
    "invoice_buyer_ban": "",
    "invoice_left_qrcode": "",
    "invoice_middle_barcode": "",
    "invoice_right_qrcode": "",
    "invoice_title_type": 1,
    "invoice_title": "",
    "invoice_amount": "0",
    "invoice_sales_amount": "0",
    "invoice_tax_amount": "0",
    "invoice_order_detail": "[]",
    "invoice_ratetype": 1,
    "invoice_input_type": null,
    "invoice_allowance": [],
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": ""
}

查詢發動後付款交易後的流程,當時候最新的訂單的相關資訊。

經銷商『後付款查詢出貨』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/afpshipmentquery"}
JSON格式,AES256加密資料
encry_data text 『後付款查詢出貨』欄位參考
JSON格式,AES256加密資料

『後付款查詢出貨』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼
uid string 訂單編號(UID)
key string 特約商店驗證碼

『後付款查詢出貨』回傳欄位

參數名稱 型態 說明 必須
uid string 訂單編號(UID)
key string(50) 交易驗証碼
code string 交易狀態碼
msg string 交易狀態訊息
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
trade_no string 後付款訂單編號
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
user_real_name string(20) 消費者真實姓名
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
shipping_info object 送貨資訊 『後付款送貨資訊』欄位參考
shipment_no string 出貨編號
delivery_code integer 貨運商家編號 『貨運商家編號』值參考
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法
refund_order array 退款訂單資訊(多筆格式) 每筆『後付款出貨查詢-退款資訊』欄位參考
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_date string 發票開立日期(YYYYMMDD)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title integer 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_allowance array 電子發票折讓資訊 每筆『電子發票折讓資訊』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5

電票交易

<?php
/**
 * 經銷商串接-直接交易-電票交易
 */
final class AgentEsvc
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['device_id'] = "01304161";
        $rawData['items'] = [['id' => '1',
                               'name' => '商品名稱',
                               'cost' => '1',
                               'amount' => '1',
                               'total' => '1']];
        $rawData['cost'] = "1";
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1";
        $rawData['pfn'] = 'ESVC';

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentEsvc = new AgentEsvc();
$AgentEsvc->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-電票交易
    /// </summary>
    public class AgentEsvc {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentEsvc simulator = new AgentEsvc();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";

            items.Add(item);

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.device_id = "01304161";
            rawData.items = items;
            rawData.cost = "10";
            rawData.user_id = "phper";
            rawData.order_id = "1234567890";
            rawData.ip = "127.0.0.1";
            rawData.pfn = "ESVC";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-電票交易
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentEsvc {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentEsvc simulator = new AgentEsvc();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "1");
        item.put("amount", "1");
        item.put("total", "1");
        items.add(item);

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("device_id", "01304161");
        rawData.put("items", items);
        rawData.put("cost", "1");
        rawData.put("user_id", "phper");
        rawData.put("order_id", "1234567890");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "ESVC");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-電票交易
 */
function AgentEsvc() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentEsvc.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        device_id: "01304161",
        items: [{
            'id': "1",
            'name': "商品名稱",
            'cost': "1",
            'amount': "1",
            'total': "1"
        }],
        cost: "1",
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "ESVC"
    };
};
/**
 * 取得服務位置
 */
AgentEsvc.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentEsvc.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentEsvc.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentEsvc.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentEsvc.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentEsvc = new AgentEsvc();
AgentEsvc.run();

import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-電票交易
"""
class AgentEsvc:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'device_id': "01304161",
            'items': [{
                'id': "1",
                'name': "商品名稱",
                'cost': "1",
                'amount': "1",
                'total': "1"
            }],
            'cost': "1",
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "ESVC"
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentEsvc = AgentEsvc()
AgentEsvc.run()

回傳 JSON 結構如下:

{
    "code": "250",
    "msg": "執行成功。",
    "uid": 83254,
    "key": "c6a40103f46c113217e9d631ccfffa05",
    "finishtime": "20210331160416",
    "cardno": "",
    "acode": "",
    "order_id": "1234567890",
    "user_id": "phper",
    "cost": 1,
    "currency": "TWD",
    "actual_cost": 1,
    "actual_currency": "TWD",
    "pfn": "EASYCARD",
    "trans_type": 1,
    "result_type": 4,
    "result_content": "{\n    \"OrderTotalCost\": \"1\",\n    \"TradeDate\": \"20210331160410\",\n    \"PaymentType\": \"06\",\n    \"Balance\": \"93\",\n    \"BeforeBalance\": \"94\",\n    \"AutoTopUpAmount\": \"0\",\n    \"CardId\": \"658355957\"\n}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": ""
}

請消費者將電子票證放於置讀卡上,然後發動電票交易,即可進行讀卡完成交易。

經銷商直接交易查詢參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『電票交易』欄位參考
JSON格式,AES256加密資料

『電票交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 (ESVC)
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type string 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
device_id string 電子票證設備ID

『電票交易』回傳欄位

參數名稱 型態 說明 必須
code string 交易回傳碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『電票類型』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content string(1000) 回傳結果 『電票交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5

電票查詢卡號

<?php
/**
 * 經銷商串接-直接交易-電票查詢卡號
 */
final class AgentEsvcQueryCardid
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['device_id'] = "01304161";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/esvcquerycardid'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentEsvcQueryCardid = new AgentEsvcQueryCardid();
$AgentEsvcQueryCardid->run();
?>
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-電票查詢卡號
    /// </summary>
    public class AgentEsvcQueryCardid {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentEsvcQueryCardid simulator = new AgentEsvcQueryCardid();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.device_id = "01304161";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/esvcquerycardid";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-電票查詢卡號
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentEsvcQueryCardid {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentEsvcQueryCardid simulator = new AgentEsvcQueryCardid();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("device_id", "01304161");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/esvcquerycardid");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-電票查詢卡號
 */
function AgentEsvcQueryCardid() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentEsvcQueryCardid.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        device_id: "01304161"
    };
};
/**
 * 取得服務位置
 */
AgentEsvcQueryCardid.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/esvcquerycardid"
    };
};
/**
 * AES 256 加密
 */
AgentEsvcQueryCardid.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentEsvcQueryCardid.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentEsvcQueryCardid.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentEsvcQueryCardid.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentEsvcQueryCardid = new AgentEsvcQueryCardid();
AgentEsvcQueryCardid.run();

import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-電票查詢卡號
"""
class AgentEsvcQueryCardid:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'device_id': "01304161"
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/esvcquerycardid'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentEsvcQueryCardid = AgentEsvcQueryCardid()
AgentEsvcQueryCardid.run()

回傳 JSON 結構如下:

{
    "code": "B200",
    "msg": "執行成功",
    "cardid": "658355957"
}

請消費者將電子票證放於置讀卡上,然後發動電票查詢卡號,即可進行讀取卡號資訊。

經銷商電票查詢卡號參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/esvcquerycardid"}
JSON格式,AES256加密資料
encry_data text 『電票查詢卡號』欄位參考
JSON格式,AES256加密資料

『電票查詢卡號』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店商務代號
device_id string 設備編號

『電票查詢卡號』回傳欄位

參數名稱 型態 說明 必須
code string 回傳碼
msg string(500) 回傳訊息
cardid string 電票卡號

電票查詢餘額

<?php
/**
 * 經銷商串接-直接交易-電票查詢餘額
 */
final class AgentEsvcQueryBalance
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['device_id'] = "01304161";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/esvcquerybalance'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentEsvcQueryBalance = new AgentEsvcQueryBalance();
$AgentEsvcQueryBalance->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-電票查詢餘額
    /// </summary>
    public class AgentEsvcQueryBalance {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentEsvcQueryBalance simulator = new AgentEsvcQueryBalance();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.device_id = "01304161";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/esvcquerybalance";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-電票查詢餘額
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentEsvcQueryBalance {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentEsvcQueryBalance simulator = new AgentEsvcQueryBalance();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("device_id", "01304161");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/esvcquerybalance");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-電票查詢餘額
 */
function AgentEsvcQueryBalance() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentEsvcQueryBalance.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        device_id: "01304161"
    };
};
/**
 * 取得服務位置
 */
AgentEsvcQueryBalance.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/esvcquerybalance"
    };
};
/**
 * AES 256 加密
 */
AgentEsvcQueryBalance.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentEsvcQueryBalance.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentEsvcQueryBalance.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentEsvcQueryBalance.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentEsvcQueryBalance = new AgentEsvcQueryBalance();
AgentEsvcQueryBalance.run();

import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-電票查詢餘額
"""
class AgentEsvcQueryBalance:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'device_id': "01304161"
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/esvcquerybalance'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentEsvcQueryBalance = AgentEsvcQueryBalance()
AgentEsvcQueryBalance.run()

回傳 JSON 結構如下:

{
    "code": "B200",
    "msg": "執行成功",
    "balance": 93,
    "cardid": "658355957",
    "cardbrand": "EASYCARD"
}

請消費者將電子票證放於置讀卡上,然後發動電票查詢餘額,即可進行讀取電子票證之餘額以及卡別資訊。

經銷商電票查詢餘額參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/esvcquerycardid"}
JSON格式,AES256加密資料
encry_data text 『電票查詢餘額』欄位參考
JSON格式,AES256加密資料

『電票查詢餘額』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店商務代號
device_id string 設備編號

『電票查詢餘額』回傳欄位

參數名稱 型態 說明 必須
code string 回傳碼
msg string(500) 回傳訊息
balance float 餘額
cardid string 電票卡號
cardbrand string 電票類型 『電票類型』值參考

電票退款

<?php
/**
 * 經銷商串接-直接交易-電票退款
 */
final class AgentEsvcRefund
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['device_id'] = "01304161";
        $rawData['uid'] = "83091";
        $rawData['key'] = "f4823bd2c2a462eaece7b7c25d0f4470";
        $rawData['cost'] = 1;

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/esvcrefund'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentEsvcRefund = new AgentEsvcRefund();
$AgentEsvcRefund->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-電票退款
    /// </summary>
    public class AgentEsvcRefund {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentEsvcRefund simulator = new AgentEsvcRefund();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.device_id = "01304161";
            rawData.uid = "83091";
            rawData.key = "f4823bd2c2a462eaece7b7c25d0f4470";
            rawData.cost = 1;

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/esvcrefund";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-電票退款
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentEsvcRefund {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentEsvcRefund simulator = new AgentEsvcRefund();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("device_id", "01304161");
        rawData.put("uid", "83091");
        rawData.put("key", "f4823bd2c2a462eaece7b7c25d0f4470");
        rawData.put("cost", 1);

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/esvcrefund");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-電票退款
 */
function AgentEsvcRefund() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentEsvcRefund.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        device_id: "01304161",
        uid: "83091",
        key: "f4823bd2c2a462eaece7b7c25d0f4470",
        cost: 1
    };
};
/**
 * 取得服務位置
 */
AgentEsvcRefund.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/esvcrefund"
    };
};
/**
 * AES 256 加密
 */
AgentEsvcRefund.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentEsvcRefund.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentEsvcRefund.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentEsvcRefund.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentEsvcRefund = new AgentEsvcRefund();
AgentEsvcRefund.run();

import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-電票退款
"""
class AgentEsvcRefund:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'device_id': "01304161",
            'uid': "83091",
            'key': "f4823bd2c2a462eaece7b7c25d0f4470",
            'cost': '1'
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/esvcrefund'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentEsvcRefund = AgentEsvcRefund()
AgentEsvcRefund.run()

回傳 JSON 結構如下:

{
    "key": "f4823bd2c2a462eaece7b7c25d0f4470",
    "uid": "83091",
    "code": "B500",
    "msg": "線上退款失敗,原因為:退款密碼錯誤。",
    "row_data": null
}

請消費者將電子票證放於置讀卡上,然後發動電票退款,即可進行退款。

經銷商電票退款參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/esvcquerycardid"}
JSON格式,AES256加密資料
encry_data text 『電票退款』欄位參考
JSON格式,AES256加密資料

『電票退款』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼
device_id string 設備編號
key string(50) 交易驗証碼
uid string 訂單編號(UID)
cost string 退款金額(可部分退款)
invoice_state integer 若有開立電子發票,指定電子發票使用作廢或折讓
注意:跨發票月份無法作廢
『電子發票退款時使用作廢或折讓』值參考
items array 退款項目
若使用電子發票,此欄位必填
退款項目必須和交易時之產品項目名稱相同
項目總金額必須與退款金額一致
每筆『商品項目』欄位參考

『電票退款』回傳欄位

參數名稱 型態 說明 必須
key string 特約商店驗證碼
uid string 訂單編號(UID)
code string 處理狀態 B200 或 B500
msg string(500) 回傳訊息
row_data object 退款資訊(退款成功才有此資訊) 『電票交易退款完成資訊』欄位參考

eACH交易

<?php
/**
 * 經銷商串接-直接交易-eACH
 */
final class AgentEach
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1";
        $rawData['pfn'] = "EACH";
        $rawData['each_code'] = "560";
        $rawData['bank_uid'] = "461";
        $rawData['bank_account'] = "00551234567890";
        $rawData['user_cellphone_code'] = "886";
        $rawData['user_cellphone'] = "924123312";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentEach = new AgentEach();
$AgentEach->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-eACH
    /// </summary>
    public class AgentEach {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentEach simulator = new AgentEach();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";

            items.Add(item);

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost = "10";
            rawData.user_id = "phper";
            rawData.order_id = "1234567890";
            rawData.ip = "127.0.0.1";
            rawData.pfn = "EACH";
            rawData.each_code = "560";
            rawData.bank_uid = "461";
            rawData.bank_account = "00551234567890";
            rawData.user_cellphone_code = "886";
            rawData.user_cellphone = "924123312";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-eACH
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentEach {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentEach simulator = new AgentEach();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", "10");
        rawData.put("user_id", "phper");
        rawData.put("order_id", "1234567890");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "EACH");
        rawData.put("each_code", "560");
        rawData.put("bank_uid", "461");
        rawData.put("bank_account", "00551234567890");
        rawData.put("user_cellphone_code", "886");
        rawData.put("user_cellphone", "924123312");


        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-eACH
 */
function AgentEach() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentEach.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [{
            'id': "1",
            'name': "商品名稱",
            'cost': "10",
            'amount': "1",
            'total': "10"
        }],
        cost: "10",
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "EACH",
        each_code: "560",
        bank_uid: "461",
        bank_account: "00551234567890",
        user_cellphone_code: "886",
        user_cellphone: "924123312"
    };
};
/**
 * 取得服務位置
 */
AgentEach.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentEach.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentEach.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentEach.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentEach.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentEach = new AgentEach();
AgentEach.run();

import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-eACH
"""
class AgentEach:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [{
                'id': "1",
                'name': "商品名稱",
                'cost': "10",
                'amount': "1",
                'total': "10"
            }],
            'cost': "10",
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "EACH",
            'each_code': "560",
            'bank_uid': "461",
            'bank_account': "00551234567890",
            'user_cellphone_code': "886",
            'user_cellphone': "924123312"
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentEach = AgentEach()
AgentEach.run()

回傳 JSON 結構如下:

{
    "code": "300",
    "msg": "執行失敗,交易失敗,原因:非EACH參加行。",
    "uid": 85390,
    "key": "9373b656ff1538a53c9845c1e30f1a8d",
    "finishtime": "",
    "cardno": "",
    "acode": "",
    "order_id": "1234567890",
    "user_id": "phper",
    "cost": 10,
    "currency": "TWD",
    "actual_cost": 0,
    "actual_currency": "TWD",
    "pfn": "EACH",
    "trans_type": 1,
    "result_type": 4,
    "result_content_type": "EACH",
    "result_content": "{\n    \"TradeNo\": \"20210507853900\"\n}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": ""
}

消費者透過網銀或金融卡申請eDDA電子化授權後,透過授權後的相關資訊,可發動eACH交易。

經銷商eACH交易參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『eACH交易』欄位參考
JSON格式,AES256加密資料

『eACH交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 『付款方式』值參考
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號 必填
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type string 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
each_code string 交易代碼(eDDA授權資訊) 必填
user_cellphone_code string(6) 手機區碼(eDDA授權資訊) 必填
user_cellphone string(20) 手機號碼(eDDA授權資訊) 必填
bank_uid string 扣款銀行代碼(eDDA授權資訊) 必填
bank_account string 扣款銀行帳號(eDDA授權資訊) 必填

『eACH交易』回傳欄位

參數名稱 型態 說明 必須
code string 交易回傳碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5

超商條碼繳費

<?php
/**
 * 經銷商串接-直接交易-超商條碼繳費
 */
final class AgentBarcode
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [
                                [
                                 'id' => '1',
                                 'name' => '商品名稱',
                                 'cost' => '10',
                                 'amount' => '1',
                                 'total' => '10'
                                ]
                            ];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1";
        $rawData['pfn'] = "BARCODE";
        $rawData['limit_pay_days'] = 40;

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentBarcode = new AgentBarcode();
$AgentBarcode->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-超商條碼繳費
    /// </summary>
    public class AgentBarcode {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentBarcode simulator = new AgentBarcode();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";
            items.Add(item);

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  10;
            rawData.user_id =  "phper";
            rawData.order_id =  "1234567890";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  "BARCODE";
            rawData.limit_pay_days =  40;

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-超商條碼繳費
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentBarcode {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentBarcode simulator = new AgentBarcode();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", 10);
        rawData.put("user_id", "phper");
        rawData.put("order_id", "1234567890");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "BARCODE");
        rawData.put("limit_pay_days", 40);

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-超商條碼繳費
 */
function AgentBarcode() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentBarcode.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [
                   {
                    'id': '1',
                    'name': '商品名稱',
                    'cost': '10',
                    'amount': '1',
                    'total': '10'
                   }
               ],
        cost: 10,
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "BARCODE",
        limit_pay_days: 40,

    };
};
/**
 * 取得服務位置
 */
AgentBarcode.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentBarcode.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentBarcode.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentBarcode.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentBarcode.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentBarcode = new AgentBarcode();
AgentBarcode.run();

import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-超商條碼繳費
"""
class AgentBarcode:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': '1',
                          'name': '商品名稱',
                          'cost': '10',
                          'amount': '1',
                          'total': '10'
                         }
                     ],
            'cost': 10,
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "BARCODE",
            'limit_pay_days': 40,
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentBarcode = AgentBarcode()
AgentBarcode.run()

回傳 JSON 結構如下:

{
    "code": "260",
    "msg": "執行成功。交易成功",
    "uid": 87071,
    "key": "1f4a2db6abd0131ae52de3af6a363594",
    "finishtime": "",
    "cardno": "",
    "acode": "",
    "card_type": "0",
    "issuing_bank": "",
    "issuing_bank_uid": "",
    "transaction_mode": "1",
    "supplier_name": "新光銀行",
    "supplier_code": "B0",
    "order_id": "1234567890",
    "user_id": "phper",
    "cost": 10,
    "currency": "TWD",
    "actual_cost": 0,
    "actual_currency": "TWD",
    "pfn": "BARCODE",
    "trans_type": 1,
    "result_type": 4,
    "result_content_type": "BARCODE",
    "result_content": "{\n    \"BarCode1\": \"1007106V6\",\n    \"BarCode2\": \"0073711910000563\",\n    \"BarCode3\": \"071048000000010\",\n    \"LimitDate\": \"20210710235959\"\n}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": ""
}

發動交易後,得到三組條碼資料,產生Barcode後讓消費者透過超商或臨櫃作繳費動作。

條碼品質及規則建議:

經銷商超商條碼繳費交易參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『超商條碼繳費』欄位參考
JSON格式,AES256加密資料

『超商條碼繳費』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 必填
『付款方式』值參考
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type string 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
limit_pay_days string 繳費有效天數(如無此資料以系統設定為預設)

『超商條碼繳費』回傳欄位

參數名稱 型態 說明 必須
code string 交易回傳碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type string 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『超商條碼繳費』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5

全支付線上交易

商家發動後會根據回應資料內容result_content中,依據使用裝置,開啟相對應的連結

因上游無提供測試資料,皆無法進行測試

<?php
/**
 * 經銷商串接-全支付線上交易
 */
final class AgentPxpayon
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880011";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "http://pay.k20-mypay.tw/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [
                                [
                                 'id' => '1',
                                 'name' => '商品名稱',
                                 'cost' => '10',
                                 'amount' => '1',
                                 'total' => '10'
                                ]
                            ];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "O20240618120110";
        $rawData['ip'] = "127.0.0.1";
        $rawData['pfn'] = "PXPAYON";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentPxpayon = new AgentPxpayon();
$AgentPxpayon->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-全支付線上交易
    /// </summary>
    public class AgentPxpayon {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880011";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "http://pay.k20-mypay.tw/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentPxpayon simulator = new AgentPxpayon();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item1 = new ExpandoObject();
            item1.id = "1";
            item1.name = "商品名稱";
            item1.cost = "10";
            item1.amount = "1";
            item1.total = "10";
            items.Add(item1);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  10;
            rawData.user_id =  "phper";
            rawData.order_id =  "O20240618120110";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  "PXPAYON";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }
    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-全支付線上交易
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentPxpayon {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880011";
    /**
     * 串接交易位置
     */
    String url = "http://pay.k20-mypay.tw/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentPxpayon simulator = new AgentPxpayon();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item1 = new HashMap<Object, Object>();
        item1.put("id", "1");
        item1.put("name", "商品名稱");
        item1.put("cost", "10");
        item1.put("amount", "1");
        item1.put("total", "10");
        items.add(item1);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", 10);
        rawData.put("user_id", "phper");
        rawData.put("order_id", "O20240618120110");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "PXPAYON");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-全支付線上交易
 */
function AgentPxpayon() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    // 特約商店商務代號
    this.storeUid = "289151880011";
    // 串接交易位置
    this.url = "http://pay.k20-mypay.tw/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentPxpayon.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [
                   {
                    'id': "1",
                    'name': "商品名稱",
                    'cost': "10",
                    'amount': "1",
                    'total': "10"
                   }
               ],
        cost: 10,
        user_id: "phper",
        order_id: "O20240618120110",
        ip: "127.0.0.1",
        pfn: "PXPAYON",

    };
};
/**
 * 取得服務位置
 */
AgentPxpayon.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentPxpayon.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentPxpayon.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentPxpayon.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentPxpayon.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentPxpayon = new AgentPxpayon();
AgentPxpayon.run();

# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-全支付線上交易
"""
class AgentPxpayon:
    # 經銷商商務代號
    agentUid = "518169081001";
    # 經銷商金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    # 特約商店商務代號
    storeUid = "289151880011"
    # 串接交易位置
    url = "http://pay.k20-mypay.tw/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': 10,
            'user_id': "phper",
            'order_id': "O20240618120110",
            'ip': "127.0.0.1",
            'pfn': "PXPAYON",
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentPxpayon = AgentPxpayon()
AgentPxpayon.run()

回傳 JSON 結構如下:

{
    "invoice_state": 0,
    "invoice_state_msg": "不處理",
    "invoice_date": "",
    "invoice_wordtrack": "",
    "invoice_number": "",
    "invoice_rand_code": "",
    "invoice_seller_ban": "",
    "invoice_seller_name": "",
    "invoice_buyer_ban": "",
    "invoice_buyer_name": "",
    "invoice_left_qrcode": "",
    "invoice_middle_barcode": "",
    "invoice_right_qrcode": "",
    "invoice_title_type": 1,
    "invoice_title": "",
    "invoice_print_type": 2,
    "invoice_print_device": 1,
    "invoice_amount": "",
    "invoice_sales_amount": "",
    "invoice_tax_amount": "",
    "invoice_order_detail": "",
    "invoice_ratetype": 1,
    "invoice_tax_rate": "",
    "invoice_remark": "",
    "invoice_input_type": 0,
    "invoice_cloud_type": 0,
    "invoice_mobile_code": "",
    "invoice_tax_id": "",
    "invoice_tax_title": "",
    "invoice_natural_person": "",
    "invoice_m_post_zone": "",
    "invoice_m_address": "",
    "invoice_love_code": "",
    "invoice_b2b_title": "",
    "invoice_b2b_id": "",
    "invoice_b2b_post_zone": "",
    "invoice_b2b_address": "",
    "code": "280",
    "msg": "執行成功。",
    "uid": 194591,
    "key": "68d2a09c31643660f29172d80dbaf9ef",
    "finishtime": "",
    "cardno": "",
    "acode": "",
    "card_type": "0",
    "issuing_bank": "",
    "issuing_bank_uid": "",
    "is_agent_charge": 0,
    "transaction_mode": "1",
    "supplier_name": "全支付",
    "supplier_code": "W8",
    "order_id": "O20240618120152",
    "user_id": "phper",
    "cost": 10,
    "currency": "TWD",
    "actual_cost": 0,
    "actual_currency": "TWD",
    "pfn": "PXPAYON",
    "actual_pay_mode": "",
    "trans_type": 1,
    "result_type": 4,
    "result_content_type": "PXPAYON",
    "result_content": "{\"Web\":\"https:\\\/\\\/uat.pxpayplus.com\\\/pxplus_ec\\\/page_redirect?data=aHR0cHM6Ly91YXQucHhwYXlwbHVzLmNvbS9xcmNvZGUvZWM%2FZGF0YT1hZ0dGQlJ0UkU3bHZrOEhOU0llRFZxMzJXNTZZbFNPZ2h4ZjJmSkx6Z1JoUFgyVTZ2SWd0cWZjM0VvYXo5SXRjbSUyZnZvcmVZd0tKdWoxN1YyUHJjaDRRJTNkJTNk&destination=PxPlus\",\"QRCodeUrl\":\"https:\\\/\\\/uat.pxpayplus.com\\\/qrcode\\\/ec?data=agGFBRtRE7lvk8HNSIeDVq32W56YlSOghxf2fJLzgRhPX2U6vIgtqfc3Eoaz9Itcm%2fvoreYwKJuj17V2Prch4Q%3d%3d\"}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": "",
    "sys_echo": ""
}

經銷商『全支付線上交易』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name":"api","cmd":"api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『全支付線上交易』欄位參考
JSON格式,AES256加密資料

『全支付線上交易』欄位

參數名稱 型態 說明 必須
store_uid string 特約商店代碼 必填
cost string 訂單總金額 必填
currency string 預設交易幣別(預設為TWD新台幣)
order_id string 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string 自訂回傳參數 1
echo_1 string 自訂回傳參數 2
echo_2 string 自訂回傳參數 3
echo_3 string 自訂回傳參數 4
echo_4 string 自訂回傳參數 5
pfn string 付費方法 (PXPAYON) 必填
discount string 折價金額 (預設0)
shipping_fee string 運費
user_id string 消費者帳號
user_name string 消費者姓名
user_real_name string 消費者真實姓名
user_english_name string 消費者英文名稱
user_zipcode string 消費者郵遞區號
user_address string 消費者地址
user_sn_type string 證號類型 『證號類型』值參考
user_sn string 付款人身分證/統一證號/護照號碼
user_phone string 消費者家用電話
user_cellphone_code string 消費者行動電話國碼
user_cellphone string 消費者行動電話
user_email string 消費者 E-Mail
user_birthday string 消費者生日
ip string 消費者來源 IP
issue_invoice_state integer 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer 電子發票稅率別 『電子發票稅率別』值參考
invoice_tax_rate float 電子發票稅率:預設0.05(零稅與免稅帶0)
invoice_remark string 發票註記(依加值中心提供註記功能)
invoice_input_type integer 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_m_post_zone string EMail 紙本寄送郵遞區號 當invoice_cloud_type為4,此欄位才有效,非必須
invoice_m_address string EMail 紙本寄送住址 當invoice_cloud_type為4,此欄位才有效,非必須
invoice_love_code string 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string 發票地址 當invoice_input_type為3時,此欄位才有效
interface string 消費者操作介面類型 pc/app
agent_sms_fee_type integer 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string 經銷商代收費
is_agent_charge integer 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考

『全支付線上交易』回傳欄位

參數名稱 型態 說明 必須
code string 交易狀態代碼
msg string 回傳訊息
uid string Payment Hub之交易流水號
key string 交易驗証碼
finishtime string 交易完成時間(YYYYMMDDHHmmss)
cardno string 銀行端口回傳碼
acode string 授權碼
card_type integer 信用卡卡別 『信用卡別類型』值參考
issuing_bank string 發卡行
issuing_bank_uid string 發卡銀行代碼
is_agent_charge int 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer 交易服務類型 『交易服務類型』值參考
supplier_name string 交易之金融服務商
supplier_code string 交易之金融服務商代碼
order_id string 貴特店系統的訂單編號
user_id string 消費者帳號
cost string 總交易金額
currency string 原交易幣別
actual_cost string 實際交易金額
actual_currency string 實際交易幣別
pfn string 付費方法 『回傳付款方式』值參考
actual_pay_mode string 實際支付方式
(當pfn為CASH-自行收款時,告知系統實際收款方式)
『自行收款付款方式』值參考
trans_type integer 交易類型 『交易類型定義』值參考
result_type string 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string 回傳結果 『全支付線上交易回傳欄位』值參考
echo_0 string 自訂回傳參數 1
echo_1 string 自訂回傳參數 2
echo_2 string 自訂回傳參數 3
echo_3 string 自訂回傳參數 4
echo_4 string 自訂回傳參數 5
invoice_state integer 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_state_msg string 發票開立狀態訊息
invoice_date string 發票開立日期(YYYYMMDDHHmmss)
invoice_wordtrack string 發票字軌
invoice_number string 發票號碼
invoice_rand_code string 電子發票隨機碼
invoice_seller_ban string 賣方統一編號
invoice_seller_name string 賣方名稱
invoice_buyer_ban string 買方統一編號
invoice_buyer_name string 買方名稱
invoice_left_qrcode string 電子發票左邊QrCode內容
invoice_middle_barcode string 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string 電子發票右邊QrCode內容
invoice_title_type integer 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string 電子發票列印標題格式
invoice_print_type integer 電子發票列印類型 『電子發票列印類型』值參考
invoice_print_device integer 電子發票列印設備 『電子發票列印設備』值參考
invoice_amount string 電子發票銷售總額
invoice_sales_amount string 電子發票銷售額
invoice_tax_amount string 電子發票稅額
invoice_order_detail string 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer 電子發票稅率別 『電子發票稅率別』值參考
invoice_tax_rate float 電子發票稅率:預設0.05(零稅與免稅帶0)
invoice_remark string 發票註記(依加值中心提供註記功能)
invoice_input_type integer 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer 電子發票開立類型-雲端發票類型 『雲端發票類型』值參考
invoice_mobile_code string 當invoice_cloud_type為2時紀錄的手機條碼
invoice_tax_id string 當invoice_cloud_type為2時紀錄的統一編號
invoice_tax_title string 當invoice_cloud_type為2時紀錄的買受人公司名稱
invoice_natural_person string 當invoice_cloud_type為3時紀錄的自然人憑證條碼
invoice_m_post_zone string 當invoice_cloud_type為4時紀錄中獎時紙本發票郵遞區號
invoice_m_address string 當invoice_cloud_type為4時紀錄中獎時紙本發票收件住址
invoice_love_code string 當invoice_input_type為2時紀錄的愛心碼
invoice_b2b_title string 當invoice_input_type為3時紀錄的發票抬頭
invoice_b2b_id string 當invoice_input_type為3時紀錄的統一編號
invoice_b2b_post_zone string 當invoice_input_type為3時紀錄的郵遞區號
invoice_b2b_address string 當invoice_input_type為3時紀錄的發票地址

全支付線下交易

消費者提供PXPay plus支付碼供設備進行掃碼做交易動作。

因上游無提供測試資料,皆無法進行測試

<?php
/**
 * 經銷商串接-直接交易-全支付線下交易
 */
final class AgentPxpayoff
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [
                                [
                                 'id' => '1',
                                 'name' => '商品名稱',
                                 'cost' => '10',
                                 'amount' => '1',
                                 'total' => '10'
                                ]
                            ];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "O20211203114630";
        $rawData['ip'] = "127.0.0.1";
        $rawData['pfn'] = "PXPAYOFF";
        $rawData['data_json'] = "{\"pxCode\":\"P1M281A4C00B2JOO1N\",\"posId\":\"1\",\"posTradeTime\":\"20211203114630\",\"remark\":\"交易註記\"}";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentPxpayoff = new AgentPxpayoff();
$AgentPxpayoff->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-全支付線下交易
    /// </summary>
    public class AgentPxpayoff {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentPxpayoff simulator = new AgentPxpayoff();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";
            items.Add(item);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  10;
            rawData.user_id =  "phper";
            rawData.order_id =  "O20211203114630";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  "PXPAYOFF";
            rawData.data_json =  "{\"pxCode\":\"P1M281A4C00B2JOO1N\",\"posId\":\"1\",\"posTradeTime\":\"20211203114630\",\"remark\":\"交易註記\"}";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-全支付線下交易
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentPxpayoff {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentPxpayoff simulator = new AgentPxpayoff();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", 10);
        rawData.put("user_id", "phper");
        rawData.put("order_id", "O20211203114630");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "PXPAYOFF");
        rawData.put("data_json", "{\"pxCode\":\"P1M281A4C00B2JOO1N\",\"posId\":\"1\",\"posTradeTime\":\"20211203114630\",\"remark\":\"交易註記\"}");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-全支付線下交易
 */
function AgentPxpayoff() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentPxpayoff.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [
                   {
                    'id': "1",
                    'name': "商品名稱",
                    'cost': "10",
                    'amount': "1",
                    'total': "10"
                   }
               ],
        cost: 10,
        user_id: "phper",
        order_id: "O20211203114630",
        ip: "127.0.0.1",
        pfn: "PXPAYOFF",
        data_json: "{\"pxCode\":\"P1M281A4C00B2JOO1N\",\"posId\":\"1\",\"posTradeTime\":\"20211203114630\",\"remark\":\"交易註記\"}",

    };
};
/**
 * 取得服務位置
 */
AgentPxpayoff.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentPxpayoff.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentPxpayoff.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentPxpayoff.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentPxpayoff.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentPxpayoff = new AgentPxpayoff();
AgentPxpayoff.run();

# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-全支付線下交易
"""
class AgentPxpayoff:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': 10,
            'user_id': "phper",
            'order_id': "O20211203114630",
            'ip': "127.0.0.1",
            'pfn': "PXPAYOFF",
            'data_json': "{\"pxCode\":\"P1M281A4C00B2JOO1N\",\"posId\":\"1\",\"posTradeTime\":\"20211203114630\",\"remark\":\"交易註記\"}",
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentPxpayoff = AgentPxpayoff()
AgentPxpayoff.run()

回傳 JSON 結構如下:

{
    "code": "250",
    "msg": "執行成功。",
    "uid": 98432,
    "key": "7f8a2b459ae296a9d3fe8fffd0d7f8d2",
    "finishtime": "20211203114635",
    "cardno": "",
    "acode": "",
    "card_type": "0",
    "issuing_bank": "",
    "issuing_bank_uid": "",
    "transaction_mode": "1",
    "supplier_name": "全支付",
    "supplier_code": "W8",
    "order_id": "O20211203114630",
    "user_id": "phper",
    "cost": 10,
    "currency": "TWD",
    "actual_cost": 10,
    "actual_currency": "TWD",
    "pfn": "PXPAYOFF",
    "trans_type": 1,
    "result_type": 4,
    "result_content_type": "PXPAYOFF",
    "result_content": "{\n    \"PosID\": \"121212\",\n    \"PosTradeTime\": \"20220101235959\",\n    \"Remark\": \"\",\n    \"TradeNo\": \"123\",\n    \"OrderTotalCost\": \"100\",\n    \"TradeDate\": \"20220101235959\",\n    \"DebitAmount\": \"100\",\n    \"InvoiceVehicle\": \"/MFX844T\",\n    \"MerMemToken\": \"TX916173531933310976\",\n    \"Pan\": \"******013000****\",\n    \"IsControversy\": \"0\"}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": "",
    "invoice_state": 0,
    "invoice_state_msg": "不處理",
    "invoice_date": "",
    "invoice_wordtrack": "",
    "invoice_number": "",
    "invoice_rand_code": "",
    "invoice_seller_ban": "",
    "invoice_buyer_ban": "",
    "invoice_left_qrcode": "",
    "invoice_middle_barcode": "",
    "invoice_right_qrcode": "",
    "invoice_title_type": 1,
    "invoice_title": "",
    "invoice_print_type": 0,
    "invoice_print_device": 0,
    "invoice_amount": "",
    "invoice_sales_amount": "",
    "invoice_tax_amount": "",
    "invoice_order_detail": "",
    "invoice_ratetype": 1,
    "invoice_input_type": 0,
    "invoice_cloud_type": 0,
    "invoice_mobile_code": "",
    "invoice_tax_id": "",
    "invoice_natural_person": "",
    "invoice_love_code": "",
    "invoice_b2b_title": "",
    "invoice_b2b_id": "",
    "invoice_b2b_post_zone": "",
    "invoice_b2b_address": ""
}

經銷商全支付線下交易參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『全支付線下交易』欄位參考
JSON格式,AES256加密資料

『直接交易-全支付線下交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 『付款方式』值參考
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
data_json string(500) 全支付線下資訊輸入(JSON格式) 『全支付線下資料』值參考

『直接交易-全支付線下交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(500) 回傳結果 『全支付線下交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_state_msg string(500) 發票開立狀態訊息
invoice_date string(14) 發票開立日期(YYYYMMDDHHmmss)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string(50) 電子發票列印標題格式
invoice_print_type integer(1) 電子發票列印類型 『電子發票列印類型』值參考
invoice_print_device integer(1) 電子發票列印設備 『電子發票列印設備』值參考
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 電子發票開立類型-雲端發票類型 『雲端發票類型』值參考
invoice_mobile_code string(20) 當invoice_cloud_type為2時紀錄的手機條碼
invoice_tax_id string(8) 當invoice_cloud_type為2時紀錄的統一編號
invoice_natural_person string(20) 當invoice_cloud_type為3時紀錄的自然人憑證條碼
invoice_love_code string(20) 當invoice_input_type為2時紀錄的愛心碼
invoice_b2b_title string(50) 當invoice_input_type為3時紀錄的發票抬頭
invoice_b2b_id string(8) 當invoice_input_type為3時紀錄的統一編號
invoice_b2b_post_zone string(10) 當invoice_input_type為3時紀錄的郵遞區號
invoice_b2b_address string(200) 當invoice_input_type為3時紀錄的發票地址

LINEPay線上交易

商家發動後會根據回應資料內容result_content中,依據使用裝置,開啟相對應的連結

<?php
/**
 * 經銷商串接-直接交易-LINEPay線上
 */
final class AgentLinepayon
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "A1234567891002";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "nq8KL8qNNCW12A3TBfAp4lU0y3PED8IQ";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "LINEPAYON";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentLinepayon = new AgentLinepayon();
$AgentLinepayon->run();
?>
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 特約商店串接-Pi錢包線下交易
    /// </summary>
    public class AgentLinepayon {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentLinepayon simulator = new AgentLinepayon();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";
            items.Add(item);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  10;
            rawData.user_id =  "phper";
            rawData.order_id =  "1234567890";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  "LINEPAYON";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.storeKey, IV);
            var svr_encode = Encrypt(svr_json, this.storeKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-Pi錢包線下交易
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentLinepayon {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentLinepayon simulator = new AgentLinepayon();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", 10);
        rawData.put("user_id", "phper");
        rawData.put("order_id", "1234567890");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "LINEPAYON");


        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-Pi錢包線下交易
 */
function AgentLinepayon() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentLinepayon.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [
            {
                'id': "1",
                'name': "商品名稱",
                'cost': "10",
                'amount': "1",
                'total': "10"
            }
        ],
        cost: 10,
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "LINEPAYON"

    };
};
/**
 * 取得服務位置
 */
AgentLinepayon.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentLinepayon.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentLinepayon.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentLinepayon.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentLinepayon.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentLinepayon = new AgentLinepayon();
AgentLinepayon.run();

# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-Pi錢包線下交易
"""
class AgentLinepayon:
    # 經銷商商務代號
    agentUid = "518169081001";
    # 經銷商金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': 10,
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "LINEPAYON"
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentLinepayon = AgentLinepayon()
AgentLinepayon.run()

回傳 JSON 結構如下:

{
  "invoice_state": 0,
  "invoice_state_msg": "不處理",
  "invoice_date": "",
  "invoice_wordtrack": "",
  "invoice_number": "",
  "invoice_rand_code": "",
  "invoice_seller_ban": "",
  "invoice_seller_name": "",
  "invoice_buyer_ban": "",
  "invoice_buyer_name": "",
  "invoice_left_qrcode": "",
  "invoice_middle_barcode": "",
  "invoice_right_qrcode": "",
  "invoice_title_type": 1,
  "invoice_title": "",
  "invoice_print_type": 2,
  "invoice_print_device": 1,
  "invoice_amount": "",
  "invoice_sales_amount": "",
  "invoice_tax_amount": "",
  "invoice_order_detail": "",
  "invoice_ratetype": 1,
  "invoice_tax_rate": "",
  "invoice_remark": "",
  "invoice_input_type": 0,
  "invoice_cloud_type": 0,
  "invoice_mobile_code": "",
  "invoice_tax_id": "",
  "invoice_tax_title": "",
  "invoice_natural_person": "",
  "invoice_love_code": "",
  "invoice_b2b_title": "",
  "invoice_b2b_id": "",
  "invoice_b2b_post_zone": "",
  "invoice_b2b_address": "",
  "code": "280",
  "msg": "執行成功。",
  "uid": 156364,
  "key": "56075c95f08a5729251af655e6315013",
  "finishtime": "",
  "cardno": "",
  "acode": "",
  "card_type": "0",
  "issuing_bank": "",
  "issuing_bank_uid": "",
  "is_agent_charge": 0,
  "transaction_mode": "1",
  "supplier_name": "台灣連線股份有限公司",
  "supplier_code": "W2",
  "order_id": "1234567890",
  "user_id": "phper",
  "cost": 10,
  "currency": "TWD",
  "actual_cost": 0,
  "actual_currency": "TWD",
  "pfn": "LINEPAYON",
  "actual_pay_mode": "",
  "trans_type": 1,
  "result_type": 4,
  "result_content_type": "LINEPAYON",
  "result_content": "{\"Web\":\"https:\\\/\\\/sandbox-web-pay.line.me\\\/web\\\/payment\\\/wait?transactionReserveId=T1RrZlpNakorU0M0MHFMdTBCditnZU9RSjBtMXNOWlM4RUdVQlFnMnN5L1ppeDBBQnVTSlpsMURlK3ZzQVcwYQ&locale=zh-TW_LP\",\"App\":\"line:\\\/\\\/pay\\\/payment\\\/T1RrZlpNakorU0M0MHFMdTBCditnZU9RSjBtMXNOWlM4RUdVQlFnMnN5L1ppeDBBQnVTSlpsMURlK3ZzQVcwYQ\",\"TradeNo\":\"2023112002042370710\"}",
  "echo_0": "",
  "echo_1": "",
  "echo_2": "",
  "echo_3": "",
  "echo_4": "",
  "sys_echo": ""
}

經銷商『LINEPay線上交易』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name":"api","cmd":"api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『LINEPay線上交易』欄位參考
JSON格式,AES256加密資料

『LINEPay線上交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 『付款方式』值參考
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_tax_rate float(5) 電子發票稅率:預設0.05(零稅與免稅帶0)
invoice_remark string(70) 發票註記(依加值中心提供註記功能)
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
success_returl string(255) 交易成功導頁網址(導頁式交易有效)
failure_returl string(255) 交易失敗導頁網址(導頁式交易有效)

『LINEPay線上交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
actual_pay_mode string(20) 實際支付方式
(當pfn為CASH-自行收款時,告知系統實際收款方式)
『自行收款付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『Line Pay線上交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5

LINE Pay線下交易

消費者提供LINE Pay支付碼供設備進行掃碼做交易動作。

<?php
/**
 * 經銷商串接-直接交易-LINEPay線下
 */
final class AgentLinepayoff
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "LINEPAYOFF";
        $rawData['data_json'] = json_encode(['linepayCode' => '314818461832250045'], JSON_UNESCAPED_UNICODE);

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentLinepayoff = new AgentLinepayoff();
$AgentLinepayoff->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-LINEPay線下
    /// </summary>
    public class AgentLinepayoff {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentLinepayoff simulator = new AgentLinepayoff();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";
            items.Add(item);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  10;
            rawData.user_id =  "phper";
            rawData.order_id =  "O20211203114630";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  "LINEPAYOFF";
            rawData.data_json =  "{\"linepayCode\":\"314818461832250045\"}";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}


import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-LINEPay線下
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentLinepayoff {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentLinepayoff simulator = new AgentLinepayoff();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", 10);
        rawData.put("user_id", "phper");
        rawData.put("order_id", "O20211203114630");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "LINEPAYOFF");
        rawData.put("data_json", "{\"linepayCode\":\"314818461832250045\"}");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}


const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-錢包被掃交易-LINEPay線下
 */
function AgentLinepayoff() {
  // 特約商店商務代號
  this.agentUid = "518169081001";
  // 特約商店金鑰或認證碼
  this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
  // 串接交易位置
  this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentLinepayoff.prototype.getRawData = function () {
  return {
    store_uid: this.storeUid,
    items: [
      {
        'id': "1",
        'name': "商品名稱",
        'cost': "10",
        'amount': "1",
        'total': "10"
      }
    ],
    cost: "10",
    user_id: "phper",
    order_id: "1234567890",
    ip: "127.0.0.1",
    pfn: "LINEPAYOFF",
    data_json: "{\"linepayCode\":\"314818461832250045\"}",

  };
};
/**
 * 取得服務位置
 */
AgentLinepayoff.prototype.getService = function () {
  return {
    service_name: "api",
    cmd: "api/transaction"
  };
};
/**
 * AES 256 加密
 */
AgentLinepayoff.prototype.encrypt = function (fields, key) {
  let eData = JSON.stringify(fields);
  const blockSize = 16;
  const iv = crypto.randomBytes(blockSize);
  const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
  let tmpCipher = encryptor.update(Buffer.from(eData));
  let finalCipher = encryptor.final();
  const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
  let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
  return data;
};
/**
 * 資料 POST 到主機
 */
AgentLinepayoff.prototype.post = function (postData) {
  return new Promise((res, rej) => {
    let options = {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      rejectUnauthorized: false
    };

    let send_process = httpRequest.request(this.url, options, (api_res) => {
      let res_data = "";
      api_res.on('data', (tmp_data) => {
        res_data += tmp_data;
      });
      api_res.on('end', () => {
        res(res_data);
      });
    });

    send_process.write(JSON.stringify(postData));
    send_process.end();
  });
};
/**
 * 取得送出欄位資料
 */
AgentLinepayoff.prototype.getPostData = function () {
  return {
    "agent_uid": this.agentUid,
    "service": this.encrypt(this.getService(), this.agentKey),
    "encry_data": this.encrypt(this.getRawData(), this.agentKey)
  };
};
/**
 * 執行
 */
AgentLinepayoff.prototype.run = async function () {
  json = await this.post(this.getPostData())
  console.log(json);
};

AgentLinepayoff = new AgentLinepayoff();
AgentLinepayoff.run();



# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-錢包被掃交易-LINEPay線下
"""
class AgentLinepayoff:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': "10",
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "LINEPAYOFF",
            'data_json': "{\"linepayCode\":\"314818461832250045\"}",
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentLinepayoff = AgentLinepayoff()
AgentLinepayoff.run()



> 回傳 JSON 結構如下:

```json
{
  "code": "250",
  "msg": "執行成功。",
  "uid": 106658,
  "key": "970f6eb5c70e3a7582e825d67cc6a289",
  "finishtime": "20220419174739",
  "cardno": "",
  "acode": "",
  "card_type": "0",
  "issuing_bank": "",
  "issuing_bank_uid": "",
  "transaction_mode": "1",
  "supplier_name": "台灣連線股份有限公司",
  "supplier_code": "W2",
  "order_id": "1234567890",
  "user_id": "phper",
  "cost": 10,
  "currency": "TWD",
  "actual_cost": 10,
  "actual_currency": "TWD",
  "pfn": "LINEPAYOFF",
  "trans_type": 1,
  "result_type": 4,
  "result_content_type": "LINEPAYOFF",
  "result_content": "{\n    \"TradeNo\": \"2022041900711036410\",\n    \"OrderTotalCost\": \"10\",\n    \"TradeDate\": \"20220419174739\",\n    \"InvoiceVehicle\": \"/MZA588U\",\n    \"RedeemAmount\": \"10\",\n    \"RedeemType\": \"1\",\n    \"OrderRealCost\": \"10\",\n    \"PaymentType\": \"\",\n    \"CreditAmt\": \"0\",\n    \"IsControversy\": \"0\"}",
  "echo_0": "",
  "echo_1": "",
  "echo_2": "",
  "echo_3": "",
  "echo_4": "",
  "invoice_state": 0,
  "invoice_state_msg": "不處理",
  "invoice_date": "",
  "invoice_wordtrack": "",
  "invoice_number": "",
  "invoice_rand_code": "",
  "invoice_seller_ban": "",
  "invoice_buyer_ban": "",
  "invoice_left_qrcode": "",
  "invoice_middle_barcode": "",
  "invoice_right_qrcode": "",
  "invoice_title_type": 1,
  "invoice_title": "",
  "invoice_print_type": 0,
  "invoice_print_device": 0,
  "invoice_amount": "",
  "invoice_sales_amount": "",
  "invoice_tax_amount": "",
  "invoice_order_detail": "",
  "invoice_ratetype": 1,
  "invoice_input_type": 0,
  "invoice_cloud_type": 0,
  "invoice_mobile_code": "",
  "invoice_tax_id": "",
  "invoice_natural_person": "",
  "invoice_love_code": "",
  "invoice_b2b_title": "",
  "invoice_b2b_id": "",
  "invoice_b2b_post_zone": "",
  "invoice_b2b_address": "",
}

經銷商LINE Pay線下交易參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『LINE Pay線下交易』欄位參考
JSON格式,AES256加密資料

『直接交易-LINE Pay線下交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號 必填
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP 必填
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
data_json string(500) LINE Pay線下資訊輸入(JSON格式) 『Line Pay線下資料』值參考

『直接交易-LINE Pay線下交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『Line Pay線下交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_state_msg string(500) 發票開立狀態訊息
invoice_date string(14) 發票開立日期(YYYYMMDDHHmmss)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string(50) 電子發票列印標題格式
invoice_print_type integer(1) 電子發票列印類型 『電子發票列印類型』值參考
invoice_print_device integer(1) 電子發票列印設備 『電子發票列印設備』值參考
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 電子發票開立類型-雲端發票類型 『雲端發票類型』值參考
invoice_mobile_code string(20) 當invoice_cloud_type為2時紀錄的手機條碼
invoice_tax_id string(8) 當invoice_cloud_type為2時紀錄的統一編號
invoice_natural_person string(20) 當invoice_cloud_type為3時紀錄的自然人憑證條碼
invoice_love_code string(20) 當invoice_input_type為2時紀錄的愛心碼
invoice_b2b_title string(50) 當invoice_input_type為3時紀錄的發票抬頭
invoice_b2b_id string(8) 當invoice_input_type為3時紀錄的統一編號
invoice_b2b_post_zone string(10) 當invoice_input_type為3時紀錄的郵遞區號
invoice_b2b_address string(200) 當invoice_input_type為3時紀錄的發票地址

Pi線上交易

商家發動後會根據回應資料內容result_content中,依據使用裝置,開啟相對應的連結

因上游無提供測試資料,皆無法進行測試

<?php
/**
 * 經銷商串接-直接交易-Pi錢包線上
 */
final class AgentPion
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "A1234567891002";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "nq8KL8qNNCW12A3TBfAp4lU0y3PED8IQ";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "PION";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentPion = new AgentPion();
$AgentPion->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-Pi錢包線下交易
    /// </summary>
    public class AgentPion {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentPion simulator = new AgentPion();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";
            items.Add(item);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  10;
            rawData.user_id =  "phper";
            rawData.order_id =  "1234567890";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  "PIOFF";
            rawData.data_json =  "{\"piCode\":\"PI24456862cukoY9JD\"}";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }
    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-Pi錢包線下交易
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentPion {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentPion simulator = new AgentPion();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", 10);
        rawData.put("user_id", "phper");
        rawData.put("order_id", "1234567890");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "PIOFF");
        rawData.put("data_json", "{\"piCode\":\"PI24456862cukoY9JD\"}");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-Pi錢包線下交易
 */
function AgentPion() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentPion.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [
            {
                'id': "1",
                'name': "商品名稱",
                'cost': "10",
                'amount': "1",
                'total': "10"
            }
        ],
        cost: 10,
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "PIOFF",
        data_json: "{\"piCode\":\"PI24456862cukoY9JD\"}",

    };
};
/**
 * 取得服務位置
 */
AgentPion.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentPion.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentPion.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentPion.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentPion.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentPion = new AgentPion();
AgentPion.run();

# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-Pi錢包線下交易
"""
class AgentPion:
    # 經銷商商務代號
    agentUid = "518169081001";
    # 經銷商金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': 10,
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "PIOFF",
            'data_json': "{\"piCode\":\"PI24456862cukoY9JD\"}",
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentPion = AgentPion()
AgentPion.run()

回傳 JSON 結構如下:

{
    "invoice_state": 0,
    "invoice_state_msg": "不處理",
    "invoice_date": "",
    "invoice_wordtrack": "",
    "invoice_number": "",
    "invoice_rand_code": "",
    "invoice_seller_ban": "",
    "invoice_seller_name": "",
    "invoice_buyer_ban": "",
    "invoice_buyer_name": "",
    "invoice_left_qrcode": "",
    "invoice_middle_barcode": "",
    "invoice_right_qrcode": "",
    "invoice_title_type": 1,
    "invoice_title": "",
    "invoice_print_type": 2,
    "invoice_print_device": 1,
    "invoice_amount": "",
    "invoice_sales_amount": "",
    "invoice_tax_amount": "",
    "invoice_order_detail": "",
    "invoice_ratetype": 1,
    "invoice_tax_rate": "",
    "invoice_remark": "",
    "invoice_input_type": 0,
    "invoice_cloud_type": 0,
    "invoice_mobile_code": "",
    "invoice_tax_id": "",
    "invoice_tax_title": "",
    "invoice_natural_person": "",
    "invoice_love_code": "",
    "invoice_b2b_title": "",
    "invoice_b2b_id": "",
    "invoice_b2b_post_zone": "",
    "invoice_b2b_address": "",
    "code": "280",
    "msg": "執行成功。",
    "uid": 156448,
    "key": "70e2119e054c78b1e1bcd8a7159021d5",
    "finishtime": "",
    "cardno": "",
    "acode": "",
    "card_type": "0",
    "issuing_bank": "",
    "issuing_bank_uid": "",
    "is_agent_charge": 0,
    "transaction_mode": "1",
    "supplier_name": "拍付國際資訊",
    "supplier_code": "W9",
    "order_id": "1234567890",
    "user_id": "phper",
    "cost": 10,
    "currency": "TWD",
    "actual_cost": 0,
    "actual_currency": "TWD",
    "pfn": "PION",
    "actual_pay_mode": "",
    "trans_type": 1,
    "result_type": 4,
    "result_content_type": "PION",
    "result_content": "{\"Web\":\"https:\\\/\\\/ap-test-wp.piapp.com.tw\\\/partner_qrcode\\\/v1\\\/payment\\\/select\\\/655b25584fe59\",\"App\":\"intent:\\\/\\\/www.piapp.com.tw?type=partner_qrcode&qrcode_url=https%3A%2F%2Fap-test.p
iapp.com.tw%2Fpartner_qrcode%2Fv1%2Fbill%2F655b25584fe59&browser=com.android.chrome#Intent;package=tw.com.pchome.android.pi.partner;scheme=pi;end;\",\"AppIOS\":\"https:\\\/\\\/ap-test.piapp.com.tw\\\/app\\\/download?type=partner_qrcode&qrcode_url=https%3A%2F%2Fap-test.piapp.com.tw%2Fpartner_qrcode%2Fv1%2Fbill%2F655b25584fe59&browser=com.android.chrome\",\"ExpiredTime\":\"20231120182232\"}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": "",
    "sys_echo": ""
}

特約商店『Pi線上交易』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name":"api","cmd":"api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『Pi線上交易』欄位參考
JSON格式,AES256加密資料

『Pi線上交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 『付款方式』值參考
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_tax_rate float(5) 電子發票稅率:預設0.05(零稅與免稅帶0)
invoice_remark string(70) 發票註記(依加值中心提供註記功能)
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
success_returl string(255) 交易成功導頁網址(導頁式交易有效)
failure_returl string(255) 交易失敗導頁網址(導頁式交易有效)

『Pi線上交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
actual_pay_mode string(20) 實際支付方式
(當pfn為CASH-自行收款時,告知系統實際收款方式)
『自行收款付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『Pi線上資料回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5

Pi線下交易

消費者提供Pi支付碼供設備進行掃碼做交易動作。

因上游無提供測試資料,皆無法進行測試

<?php
/**
 * 經銷商串接-直接交易-Pi錢包線下
 */
final class AgentPioff
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "PIOFF";
        $rawData['data_json'] = json_encode(['piCode' => 'PI7E3A60BD8C8F23F6'], JSON_UNESCAPED_UNICODE);

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentPioff = new AgentPioff();
$AgentPioff->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-Pi錢包線下
    /// </summary>
    public class AgentPioff {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentPioff simulator = new AgentPioff();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";
            items.Add(item);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  10;
            rawData.user_id =  "phper";
            rawData.order_id =  "O20211203114630";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  "PIOFF";
            rawData.data_json =  "{\"piCode\":\"PI7E3A60BD8C8F23F6\"}";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}


import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-Pi錢包線下
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentPioff {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentPioff simulator = new AgentPioff();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", 10);
        rawData.put("user_id", "phper");
        rawData.put("order_id", "O20211203114630");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "PIOFF");
        rawData.put("data_json", "{\"piCode\":\"PI7E3A60BD8C8F23F6\"}");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}


const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-錢包被掃交易-Pi錢包線下
 */
function AgentPioff() {
  // 特約商店商務代號
  this.agentUid = "518169081001";
  // 特約商店金鑰或認證碼
  this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
  // 串接交易位置
  this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentPioff.prototype.getRawData = function () {
  return {
    store_uid: this.storeUid,
    items: [
      {
        'id': "1",
        'name': "商品名稱",
        'cost': "10",
        'amount': "1",
        'total': "10"
      }
    ],
    cost: "10",
    user_id: "phper",
    order_id: "1234567890",
    ip: "127.0.0.1",
    pfn: "PIOFF",
    data_json: "{\"piCode\":\"PI7E3A60BD8C8F23F6\"}",

  };
};
/**
 * 取得服務位置
 */
AgentPioff.prototype.getService = function () {
  return {
    service_name: "api",
    cmd: "api/transaction"
  };
};
/**
 * AES 256 加密
 */
AgentPioff.prototype.encrypt = function (fields, key) {
  let eData = JSON.stringify(fields);
  const blockSize = 16;
  const iv = crypto.randomBytes(blockSize);
  const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
  let tmpCipher = encryptor.update(Buffer.from(eData));
  let finalCipher = encryptor.final();
  const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
  let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
  return data;
};
/**
 * 資料 POST 到主機
 */
AgentPioff.prototype.post = function (postData) {
  return new Promise((res, rej) => {
    let options = {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      rejectUnauthorized: false
    };

    let send_process = httpRequest.request(this.url, options, (api_res) => {
      let res_data = "";
      api_res.on('data', (tmp_data) => {
        res_data += tmp_data;
      });
      api_res.on('end', () => {
        res(res_data);
      });
    });

    send_process.write(JSON.stringify(postData));
    send_process.end();
  });
};
/**
 * 取得送出欄位資料
 */
AgentPioff.prototype.getPostData = function () {
  return {
    "agent_uid": this.agentUid,
    "service": this.encrypt(this.getService(), this.agentKey),
    "encry_data": this.encrypt(this.getRawData(), this.agentKey)
  };
};
/**
 * 執行
 */
AgentPioff.prototype.run = async function () {
  json = await this.post(this.getPostData())
  console.log(json);
};

AgentPioff = new AgentPioff();
AgentPioff.run();


# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-錢包被掃交易-Pi錢包線下
"""
class AgentPioff:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': "10",
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "PIOFF",
            'data_json': "{\"piCode\":\"PI7E3A60BD8C8F23F6\"}",
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentPioff = AgentPioff()
AgentPioff.run()


回傳 JSON 結構如下:

{
  "code": "250",
  "msg": "執行成功。",
  "uid": 106658,
  "key": "970f6eb5c70e3a7582e825d67cc6a289",
  "finishtime": "20220419174739",
  "cardno": "",
  "acode": "",
  "card_type": "0",
  "issuing_bank": "",
  "issuing_bank_uid": "",
  "transaction_mode": "1",
  "supplier_name": "台灣連線股份有限公司",
  "supplier_code": "W2",
  "order_id": "1234567890",
  "user_id": "phper",
  "cost": 10,
  "currency": "TWD",
  "actual_cost": 10,
  "actual_currency": "TWD",
  "pfn": "PIOFF",
  "trans_type": 1,
  "result_type": 4,
  "result_content_type": "PIOFF",
  "result_content": "{\n    \"TradeNo\": \"TX2226274154701960\",\n    \"OrderTotalCost\": \"10\",\n    \"TradeDate\": \"20220419174739\",\n    \"CarrierCode\": \"/VXXP-O2\"\n}",
  "echo_0": "",
  "echo_1": "",
  "echo_2": "",
  "echo_3": "",
  "echo_4": "",
  "invoice_state": 0,
  "invoice_state_msg": "不處理",
  "invoice_date": "",
  "invoice_wordtrack": "",
  "invoice_number": "",
  "invoice_rand_code": "",
  "invoice_seller_ban": "",
  "invoice_buyer_ban": "",
  "invoice_left_qrcode": "",
  "invoice_middle_barcode": "",
  "invoice_right_qrcode": "",
  "invoice_title_type": 1,
  "invoice_title": "",
  "invoice_print_type": 0,
  "invoice_print_device": 0,
  "invoice_amount": "",
  "invoice_sales_amount": "",
  "invoice_tax_amount": "",
  "invoice_order_detail": "",
  "invoice_ratetype": 1,
  "invoice_input_type": 0,
  "invoice_cloud_type": 0,
  "invoice_mobile_code": "",
  "invoice_tax_id": "",
  "invoice_natural_person": "",
  "invoice_love_code": "",
  "invoice_b2b_title": "",
  "invoice_b2b_id": "",
  "invoice_b2b_post_zone": "",
  "invoice_b2b_address": "",
}

經銷商Pi線下交易參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『Pi線下交易』欄位參考
JSON格式,AES256加密資料

『直接交易-Pi線下交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號 必填
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP 必填
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
data_json string(500) Pi線下資訊輸入(JSON格式) 『Pi線下資料』值參考

『直接交易-Pi線下交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『Pi線下交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_state_msg string(500) 發票開立狀態訊息
invoice_date string(14) 發票開立日期(YYYYMMDDHHmmss)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string(50) 電子發票列印標題格式
invoice_print_type integer(1) 電子發票列印類型 『電子發票列印類型』值參考
invoice_print_device integer(1) 電子發票列印設備 『電子發票列印設備』值參考
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 電子發票開立類型-雲端發票類型 『雲端發票類型』值參考
invoice_mobile_code string(20) 當invoice_cloud_type為2時紀錄的手機條碼
invoice_tax_id string(8) 當invoice_cloud_type為2時紀錄的統一編號
invoice_natural_person string(20) 當invoice_cloud_type為3時紀錄的自然人憑證條碼
invoice_love_code string(20) 當invoice_input_type為2時紀錄的愛心碼
invoice_b2b_title string(50) 當invoice_input_type為3時紀錄的發票抬頭
invoice_b2b_id string(8) 當invoice_input_type為3時紀錄的統一編號
invoice_b2b_post_zone string(10) 當invoice_input_type為3時紀錄的郵遞區號
invoice_b2b_address string(200) 當invoice_input_type為3時紀錄的發票地址

微信線下交易

消費者提供微信支付碼供設備進行掃碼做交易動作。

因上游無提供測試資料,皆無法進行測試

<?php
/**
 * 經銷商串接-直接交易-微信線下
 */
final class AgentWechatoff
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "WECHATOFF";
        $rawData['data_json'] = json_encode(['wechatCode' => '134507721102798524'], JSON_UNESCAPED_UNICODE);

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentWechatoff = new AgentWechatoff();
$AgentWechatoff->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-微信線下
    /// </summary>
    public class AgentWechatoff {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentWechatoff simulator = new AgentWechatoff();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";
            items.Add(item);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  10;
            rawData.user_id =  "phper";
            rawData.order_id =  "O20211203114630";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  "WECHATOFF";
            rawData.data_json =  "{\"wechatCode\":\"134507721102798524\"}";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}


import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-微信線下
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentWechatoff {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentWechatoff simulator = new AgentWechatoff();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", 10);
        rawData.put("user_id", "phper");
        rawData.put("order_id", "O20211203114630");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "WECHATOFF");
        rawData.put("data_json", "{\"wechatCode\":\"134507721102798524\"}");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}


const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-錢包被掃交易-微信線下
 */
function AgentWechatoff() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentWechatoff.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [
            {
                'id': "1",
                'name': "商品名稱",
                'cost': "10",
                'amount': "1",
                'total': "10"
            }
        ],
        cost: "10",
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "WECHATOFF",
        data_json: "{\"wechatCode\":\"134507721102798524\"}",

    };
};
/**
 * 取得服務位置
 */
AgentWechatoff.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentWechatoff.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentWechatoff.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentWechatoff.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentWechatoff.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentWechatoff = new AgentWechatoff();
AgentWechatoff.run();


# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-錢包被掃交易-微信線下
"""
class AgentWechatoff:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': "10",
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "WECHATOFF",
            'data_json': "{\"wechatCode\":\"134507721102798524\"}",
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentWechatoff = AgentWechatoff()
AgentWechatoff.run()


回傳 JSON 結構如下:

{
  "code": "250",
  "msg": "執行成功。",
  "uid": 106658,
  "key": "970f6eb5c70e3a7582e825d67cc6a289",
  "finishtime": "20220419174739",
  "cardno": "",
  "acode": "",
  "card_type": "0",
  "issuing_bank": "",
  "issuing_bank_uid": "",
  "transaction_mode": "1",
  "supplier_name": "台灣連線股份有限公司",
  "supplier_code": "W2",
  "order_id": "1234567890",
  "user_id": "phper",
  "cost": 10,
  "currency": "TWD",
  "actual_cost": 10,
  "actual_currency": "TWD",
  "pfn": "WECHATOFF",
  "trans_type": 1,
  "result_type": 4,
  "result_content_type": "WECHATOFF",
  "result_content": "{}",
  "echo_0": "",
  "echo_1": "",
  "echo_2": "",
  "echo_3": "",
  "echo_4": "",
  "invoice_state": 0,
  "invoice_state_msg": "不處理",
  "invoice_date": "",
  "invoice_wordtrack": "",
  "invoice_number": "",
  "invoice_rand_code": "",
  "invoice_seller_ban": "",
  "invoice_buyer_ban": "",
  "invoice_left_qrcode": "",
  "invoice_middle_barcode": "",
  "invoice_right_qrcode": "",
  "invoice_title_type": 1,
  "invoice_title": "",
  "invoice_print_type": 0,
  "invoice_print_device": 0,
  "invoice_amount": "",
  "invoice_sales_amount": "",
  "invoice_tax_amount": "",
  "invoice_order_detail": "",
  "invoice_ratetype": 1,
  "invoice_input_type": 0,
  "invoice_cloud_type": 0,
  "invoice_mobile_code": "",
  "invoice_tax_id": "",
  "invoice_natural_person": "",
  "invoice_love_code": "",
  "invoice_b2b_title": "",
  "invoice_b2b_id": "",
  "invoice_b2b_post_zone": "",
  "invoice_b2b_address": "",
}

經銷商微信線下交易參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『微信線下交易』欄位參考
JSON格式,AES256加密資料

『直接交易-微信線下交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號 必填
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP 必填
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
data_json string(500) 微信線下資訊輸入(JSON格式) 『街口線下資料』值參考

『直接交易-微信線下交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『微信線下交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_state_msg string(500) 發票開立狀態訊息
invoice_date string(14) 發票開立日期(YYYYMMDDHHmmss)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string(50) 電子發票列印標題格式
invoice_print_type integer(1) 電子發票列印類型 『電子發票列印類型』值參考
invoice_print_device integer(1) 電子發票列印設備 『電子發票列印設備』值參考
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 電子發票開立類型-雲端發票類型 『雲端發票類型』值參考
invoice_mobile_code string(20) 當invoice_cloud_type為2時紀錄的手機條碼
invoice_tax_id string(8) 當invoice_cloud_type為2時紀錄的統一編號
invoice_natural_person string(20) 當invoice_cloud_type為3時紀錄的自然人憑證條碼
invoice_love_code string(20) 當invoice_input_type為2時紀錄的愛心碼
invoice_b2b_title string(50) 當invoice_input_type為3時紀錄的發票抬頭
invoice_b2b_id string(8) 當invoice_input_type為3時紀錄的統一編號
invoice_b2b_post_zone string(10) 當invoice_input_type為3時紀錄的郵遞區號
invoice_b2b_address string(200) 當invoice_input_type為3時紀錄的發票地址

街口線上交易

因上游無提供測試資料,皆無法進行測試

<?php
/**
 * 經銷商串接-直接交易-街口支付線上
 */
final class AgentJkoon
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "A1234567891002";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "nq8KL8qNNCW12A3TBfAp4lU0y3PED8IQ";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "JKOON";
        $rawData['success_returl'] = "http://www.google.com.tw";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentJkoon = new AgentJkoon();
$AgentJkoon->run();
?>
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-Pi錢包線下交易
    /// </summary>
    public class AgentJKOon {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentJKOon simulator = new AgentJKOon();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";
            items.Add(item);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  10;
            rawData.user_id =  "phper";
            rawData.order_id =  "1234567890";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  "PIOFF";
            rawData.data_json =  "{\"piCode\":\"PI24456862cukoY9JD\"}";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }
    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-Pi錢包線下交易
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentJKOon {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentJKOon simulator = new AgentJKOon();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", 10);
        rawData.put("user_id", "phper");
        rawData.put("order_id", "1234567890");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "PIOFF");
        rawData.put("data_json", "{\"piCode\":\"PI24456862cukoY9JD\"}");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-Pi錢包線下交易
 */
function AgentJKOon() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentJKOon.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [
            {
                'id': "1",
                'name': "商品名稱",
                'cost': "10",
                'amount': "1",
                'total': "10"
            }
        ],
        cost: 10,
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "PIOFF",
        data_json: "{\"piCode\":\"PI24456862cukoY9JD\"}",

    };
};
/**
 * 取得服務位置
 */
AgentJKOon.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentJKOon.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentJKOon.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentJKOon.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentJKOon.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentJKOon = new AgentJKOon();
AgentJKOon.run();

# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-Pi錢包線下交易
"""
class AgentJKOon:
    # 經銷商商務代號
    agentUid = "518169081001";
    # 經銷商金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': 10,
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "PIOFF",
            'data_json': "{\"piCode\":\"PI24456862cukoY9JD\"}",
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentJKOon = AgentJKOon()
AgentJKOon.run()

回傳 JSON 結構如下:

{
    "invoice_state": 0,
    "invoice_state_msg": "不處理",
    "invoice_date": "",
    "invoice_wordtrack": "",
    "invoice_number": "",
    "invoice_rand_code": "",
    "invoice_seller_ban": "",
    "invoice_seller_name": "",
    "invoice_buyer_ban": "",
    "invoice_buyer_name": "",
    "invoice_left_qrcode": "",
    "invoice_middle_barcode": "",
    "invoice_right_qrcode": "",
    "invoice_title_type": 1,
    "invoice_title": "",
    "invoice_print_type": 2,
    "invoice_print_device": 1,
    "invoice_amount": "",
    "invoice_sales_amount": "",
    "invoice_tax_amount": "",
    "invoice_order_detail": "",
    "invoice_ratetype": 1,
    "invoice_tax_rate": "",
    "invoice_remark": "",
    "invoice_input_type": 0,
    "invoice_cloud_type": 0,
    "invoice_mobile_code": "",
    "invoice_tax_id": "",
    "invoice_tax_title": "",
    "invoice_natural_person": "",
    "invoice_love_code": "",
    "invoice_b2b_title": "",
    "invoice_b2b_id": "",
    "invoice_b2b_post_zone": "",
    "invoice_b2b_address": "",
    "code": "280",
    "msg": "執行成功。",
    "uid": 156449,
    "key": "ed35ea0459c28b0f91573e7731c377ca",
    "finishtime": "",
    "cardno": "",
    "acode": "",
    "card_type": "0",
    "issuing_bank": "",
    "issuing_bank_uid": "",
    "is_agent_charge": 0,
    "transaction_mode": "1",
    "supplier_name": "街口電子支付",
    "supplier_code": "W4",
    "order_id": "1234567890",
    "user_id": "phper",
    "cost": 10,
    "currency": "TWD",
    "actual_cost": 0,
    "actual_currency": "TWD",
    "pfn": "JKOON",
    "actual_pay_mode": "",
    "trans_type": 1,
    "result_type": 4,
    "result_content_type": "JKOON",
    "result_content": "{\"Web\":\"https:\\\/\\\/uat-onlinepay.jkopay.app\\\/web\\\/paymentRouter?j=OL%231%3AENT%23bENQNkFWRkxYL2tmeWZoOUlUL2VBZz09%3AS%2303eb9890-4c78-11e9-8d1a-0050568403ed%3AA%2310%3ACUR%23TWD%3ASRC%23REDIRECT_MWEB
%3AUNRDM%230%3AFX%230%3ATA%2310%3ATCUR%23TWD%3AFXR%231.00%3AUR%231%3AD%23D&s=21e567dcb56036dbda741182255c31de9325dddd5b37eb9e805ff7b4b4b6775f\",\"OrderTotalCost\":\"10\",\"ExpiredTime\":\"1700473798\",\"QRCodeUrl\":\"https:\\\/\\\/u
at-onlinepay.jkopay.app\\\/web\\\/qr?j=OL%231%3AENT%23bENQNkFWRkxYL2tmeWZoOUlUL2VBZz09%3AS%2303eb9890-4c78-11e9-8d1a-0050568403ed%3AA%2310%3ACUR%23TWD%3ASRC%23REDIRECT_MWEB%3AUNRDM%230%3AFX%230%3ATA%2310%3ATCUR%23TWD%3AFXR%231.00%3AUR%231%3AD%23D&s=21e567dcb56036dbda741182255c31de9325dddd5b37eb9e805ff7b4b4b6775f\"}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": "",
    "sys_echo": ""
}

特約商店『街口線上交易』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name":"api","cmd":"api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『街口線上交易』欄位參考
JSON格式,AES256加密資料
參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 『付款方式』值參考
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_tax_rate float(5) 電子發票稅率:預設0.05(零稅與免稅帶0)
invoice_remark string(70) 發票註記(依加值中心提供註記功能)
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
success_returl string(255) 交易成功導頁網址(導頁式交易有效)
failure_returl string(255) 交易失敗導頁網址(導頁式交易有效)

『街口線上交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
actual_pay_mode string(20) 實際支付方式
(當pfn為CASH-自行收款時,告知系統實際收款方式)
『自行收款付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『街口線上交易』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5

街口線下交易

消費者提供街口支付碼供設備進行掃碼做交易動作。

因上游無提供測試資料,皆無法進行測試

<?php
/**
 * 經銷商串接-直接交易-街口支付線下
 */
final class AgentJkooff
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['user_email'] = "[email protected]";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "JKOOFF";
        $rawData['data_json'] = json_encode(['jkoCode' => '22J111111111111111', 'posId' => '1', 'posTradeTime' => date("YmdHis"), 'remark' => '交易註記'], JSON_UNESCAPED_UNICODE);

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentJkooff = new AgentJkooff();
$AgentJkooff->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-街口支付線下
    /// </summary>
    public class AgentJkooff {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentJkooff simulator = new AgentJkooff();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";
            items.Add(item);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  10;
            rawData.user_id =  "phper";
            rawData.order_id =  "O20211203114630";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  "JKOOFF";
            rawData.data_json =  "{\"jkoCode\":\"22J111111111111111\",\"posId\":\"1\",\"posTradeTime\":\"20220422114630\",\"remark\":\"交易註記\"}";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}


import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-街口支付線下
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentJkooff {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentJkooff simulator = new AgentJkooff();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", 10);
        rawData.put("user_id", "phper");
        rawData.put("order_id", "O20211203114630");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "JKOOFF");
        rawData.put("data_json", "{\"jkoCode\":\"22J111111111111111\",\"posId\":\"1\",\"posTradeTime\":\"20220422114630\",\"remark\":\"交易註記\"}");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}


const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-錢包被掃交易-街口支付線下
 */
function AgentJkooff() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentJkooff.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [
            {
                'id': "1",
                'name': "商品名稱",
                'cost': "10",
                'amount': "1",
                'total': "10"
            }
        ],
        cost: "10",
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "JKOOFF",
        data_json: "{\"jkoCode\":\"22J111111111111111\",\"posId\":\"1\",\"posTradeTime\":\"20220422114630\",\"remark\":\"交易註記\"}",

    };
};
/**
 * 取得服務位置
 */
AgentJkooff.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentJkooff.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentJkooff.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentJkooff.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentJkooff.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentJkooff = new AgentJkooff();
AgentJkooff.run();


# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-錢包被掃交易-街口支付線下
"""
class AgentJkooff:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': "10",
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "JKOOFF",
            'data_json': "{\"jkoCode\":\"22J111111111111111\",\"posId\":\"1\",\"posTradeTime\":\"20220422114630\",\"remark\":\"交易註記\"}",
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentJkooff = AgentJkooff()
AgentJkooff.run()


回傳 JSON 結構如下:

{
  "code": "250",
  "msg": "執行成功。",
  "uid": 106658,
  "key": "970f6eb5c70e3a7582e825d67cc6a289",
  "finishtime": "20220419174739",
  "cardno": "",
  "acode": "",
  "card_type": "0",
  "issuing_bank": "",
  "issuing_bank_uid": "",
  "transaction_mode": "1",
  "supplier_name": "台灣連線股份有限公司",
  "supplier_code": "W2",
  "order_id": "1234567890",
  "user_id": "phper",
  "cost": 10,
  "currency": "TWD",
  "actual_cost": 10,
  "actual_currency": "TWD",
  "pfn": "JKOOFF",
  "trans_type": 1,
  "result_type": 4,
  "result_content_type": "JKOOFF",
  "result_content": "{}",
  "echo_0": "",
  "echo_1": "",
  "echo_2": "",
  "echo_3": "",
  "echo_4": "",
  "invoice_state": 0,
  "invoice_state_msg": "不處理",
  "invoice_date": "",
  "invoice_wordtrack": "",
  "invoice_number": "",
  "invoice_rand_code": "",
  "invoice_seller_ban": "",
  "invoice_buyer_ban": "",
  "invoice_left_qrcode": "",
  "invoice_middle_barcode": "",
  "invoice_right_qrcode": "",
  "invoice_title_type": 1,
  "invoice_title": "",
  "invoice_print_type": 0,
  "invoice_print_device": 0,
  "invoice_amount": "",
  "invoice_sales_amount": "",
  "invoice_tax_amount": "",
  "invoice_order_detail": "",
  "invoice_ratetype": 1,
  "invoice_input_type": 0,
  "invoice_cloud_type": 0,
  "invoice_mobile_code": "",
  "invoice_tax_id": "",
  "invoice_natural_person": "",
  "invoice_love_code": "",
  "invoice_b2b_title": "",
  "invoice_b2b_id": "",
  "invoice_b2b_post_zone": "",
  "invoice_b2b_address": "",
}

經銷商街口線下交易參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『街口線下交易』欄位參考
JSON格式,AES256加密資料

『直接交易-街口線下交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號 必填
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP 必填
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
data_json string(500) 街口線下資訊輸入(JSON格式) 『街口線下資料』值參考

『直接交易-街口線下交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『街口線下交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_state_msg string(500) 發票開立狀態訊息
invoice_date string(14) 發票開立日期(YYYYMMDDHHmmss)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string(50) 電子發票列印標題格式
invoice_print_type integer(1) 電子發票列印類型 『電子發票列印類型』值參考
invoice_print_device integer(1) 電子發票列印設備 『電子發票列印設備』值參考
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 電子發票開立類型-雲端發票類型 『雲端發票類型』值參考
invoice_mobile_code string(20) 當invoice_cloud_type為2時紀錄的手機條碼
invoice_tax_id string(8) 當invoice_cloud_type為2時紀錄的統一編號
invoice_natural_person string(20) 當invoice_cloud_type為3時紀錄的自然人憑證條碼
invoice_love_code string(20) 當invoice_input_type為2時紀錄的愛心碼
invoice_b2b_title string(50) 當invoice_input_type為3時紀錄的發票抬頭
invoice_b2b_id string(8) 當invoice_input_type為3時紀錄的統一編號
invoice_b2b_post_zone string(10) 當invoice_input_type為3時紀錄的郵遞區號
invoice_b2b_address string(200) 當invoice_input_type為3時紀錄的發票地址

Apple Pay線下交易

消費者提供Apple Pay支付碼供設備進行掃碼做交易動作。
需要去申請憑證,再將憑證給予我司

<?php
/**
 * 經銷商串接-直接交易-Apple Pay
 */
final class AgentApplepay
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "APPLEPAY";
        $rawData['data_json'] = '{"paymentData":{"version":"RSA_v1","data":"","signature":"","header":{"publicKeyHash":"","transactionId":"","wrappedKey":""}},"paymentMethod":{"displayName":"Visa 0492","network":"Visa","type":"debit"},"transactionIdentifier":""}';

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentApplepay = new AgentApplepay();
$AgentApplepay->run();
?>

回傳 JSON 結構如下:

{
  "code": "250",
  "msg": "執行成功。",
  "uid": 106658,
  "key": "970f6eb5c70e3a7582e825d67cc6a289",
  "finishtime": "20220419174739",
  "cardno": "",
  "acode": "",
  "card_type": "0",
  "issuing_bank": "",
  "issuing_bank_uid": "",
  "transaction_mode": "1",
  "supplier_name": "台灣連線股份有限公司",
  "supplier_code": "W2",
  "order_id": "1234567890",
  "user_id": "phper",
  "cost": 10,
  "currency": "TWD",
  "actual_cost": 10,
  "actual_currency": "TWD",
  "pfn": "APPLEPAY",
  "trans_type": 1,
  "result_type": 4,
  "result_content_type": "APPLEPAY",
  "result_content": "{}",
  "echo_0": "",
  "echo_1": "",
  "echo_2": "",
  "echo_3": "",
  "echo_4": "",
  "invoice_state": 0,
  "invoice_state_msg": "不處理",
  "invoice_date": "",
  "invoice_wordtrack": "",
  "invoice_number": "",
  "invoice_rand_code": "",
  "invoice_seller_ban": "",
  "invoice_buyer_ban": "",
  "invoice_left_qrcode": "",
  "invoice_middle_barcode": "",
  "invoice_right_qrcode": "",
  "invoice_title_type": 1,
  "invoice_title": "",
  "invoice_print_type": 0,
  "invoice_print_device": 0,
  "invoice_amount": "",
  "invoice_sales_amount": "",
  "invoice_tax_amount": "",
  "invoice_order_detail": "",
  "invoice_ratetype": 1,
  "invoice_input_type": 0,
  "invoice_cloud_type": 0,
  "invoice_mobile_code": "",
  "invoice_tax_id": "",
  "invoice_natural_person": "",
  "invoice_love_code": "",
  "invoice_b2b_title": "",
  "invoice_b2b_id": "",
  "invoice_b2b_post_zone": "",
  "invoice_b2b_address": "",
}

經銷商Apple Pay線下交易參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『ApplePay線下交易』欄位參考
JSON格式,AES256加密資料

『直接交易-Apple Pay線下交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號 必填
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP 必填
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
data_json string(500) Apple Pay線下資訊輸入(JSON格式) 『Apple Pay線下資料』值參考

『直接交易-Apple Pay線下交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『Apple Pay線下交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_state_msg string(500) 發票開立狀態訊息
invoice_date string(14) 發票開立日期(YYYYMMDDHHmmss)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string(50) 電子發票列印標題格式
invoice_print_type integer(1) 電子發票列印類型 『電子發票列印類型』值參考
invoice_print_device integer(1) 電子發票列印設備 『電子發票列印設備』值參考
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 電子發票開立類型-雲端發票類型 『雲端發票類型』值參考
invoice_mobile_code string(20) 當invoice_cloud_type為2時紀錄的手機條碼
invoice_tax_id string(8) 當invoice_cloud_type為2時紀錄的統一編號
invoice_natural_person string(20) 當invoice_cloud_type為3時紀錄的自然人憑證條碼
invoice_love_code string(20) 當invoice_input_type為2時紀錄的愛心碼
invoice_b2b_title string(50) 當invoice_input_type為3時紀錄的發票抬頭
invoice_b2b_id string(8) 當invoice_input_type為3時紀錄的統一編號
invoice_b2b_post_zone string(10) 當invoice_input_type為3時紀錄的郵遞區號
invoice_b2b_address string(200) 當invoice_input_type為3時紀錄的發票地址

Google Pay線下交易

消費者提供Goole Pay支付碼供設備進行掃碼做交易動作。
需要準備
1.提供domain
2.項目選擇(當使用者瀏覽項目或服務時)
3.預購畫面(當用戶最終準備好購買時)
4.付款方式畫面(當用戶選擇 Google Pay 作為付款方式)
5.Google Pay API 付款畫面(當用戶看到他們儲存到 Google Pay 的付款資訊。提示:Android 不允許您拍攝此畫面的螢幕截圖,因此請使用其他裝置拍攝螢幕的照片)
6.購買後螢幕(當用戶成功購買)

ps.只能用於app開啟webview或網頁交易,無法使用應用程式做交易

<?php
/**
 * 經銷商串接-直接交易-Google Pay
 */
final class AgentGooglepay
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "GOOGLEPAY";
        $rawData['data_json'] = "{\"apiVersionMinor\": 0,   \"apiVersion\": 2,\"paymentMethodData\": {\"description\": \"Visa??????1234\",\"tokenizationData\": {\"type\": \"PAYMENT_GATEWAY\",\"token\": \"{\\\"signature\\\":\\\"MEQCICA????\\\\u003d\\\\u003d\\\",\\\"protocolVersion\\\":\\\"ECv1\\\",\\\"signedMessage\\\":\\\"{\\\\\\\"encryptedMessage\\\\\\\":\\\\\\\"2oGYBPrbBJIAg????\\\\\\\\u003d\\\\\\\\u003d\\\\\\\",\\\\\\\"ephemeralPublicKey\\\\\\\":\\\\\\\"BOlRJqnD????\\\\\\\\u003d\\\\\\\",\\\\\\\"tag\\\\\\\":\\\\\\\"g0lZC4????\\\\\\\\u003d\\\\\\\"}\\\"}\"},\"type\": \"CARD\",\"info\": {\"cardNetwork\": \"VISA\",\"cardDetails\": \"1234\"}}}";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentGooglepay = new AgentGooglepay();
$AgentGooglepay->run();
?>

回傳 JSON 結構如下:

{
  "code": "250",
  "msg": "執行成功。",
  "uid": 106658,
  "key": "970f6eb5c70e3a7582e825d67cc6a289",
  "finishtime": "20220419174739",
  "cardno": "",
  "acode": "",
  "card_type": "0",
  "issuing_bank": "",
  "issuing_bank_uid": "",
  "transaction_mode": "1",
  "supplier_name": "台灣連線股份有限公司",
  "supplier_code": "W2",
  "order_id": "1234567890",
  "user_id": "phper",
  "cost": 10,
  "currency": "TWD",
  "actual_cost": 10,
  "actual_currency": "TWD",
  "pfn": "GOOGLEPAY",
  "trans_type": 1,
  "result_type": 4,
  "result_content_type": "GOOGLEPAY",
  "result_content": "{}",
  "echo_0": "",
  "echo_1": "",
  "echo_2": "",
  "echo_3": "",
  "echo_4": "",
  "invoice_state": 0,
  "invoice_state_msg": "不處理",
  "invoice_date": "",
  "invoice_wordtrack": "",
  "invoice_number": "",
  "invoice_rand_code": "",
  "invoice_seller_ban": "",
  "invoice_buyer_ban": "",
  "invoice_left_qrcode": "",
  "invoice_middle_barcode": "",
  "invoice_right_qrcode": "",
  "invoice_title_type": 1,
  "invoice_title": "",
  "invoice_print_type": 0,
  "invoice_print_device": 0,
  "invoice_amount": "",
  "invoice_sales_amount": "",
  "invoice_tax_amount": "",
  "invoice_order_detail": "",
  "invoice_ratetype": 1,
  "invoice_input_type": 0,
  "invoice_cloud_type": 0,
  "invoice_mobile_code": "",
  "invoice_tax_id": "",
  "invoice_natural_person": "",
  "invoice_love_code": "",
  "invoice_b2b_title": "",
  "invoice_b2b_id": "",
  "invoice_b2b_post_zone": "",
  "invoice_b2b_address": "",
}

經銷商Google Pay線下交易參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『GooglePay線下交易』欄位參考
JSON格式,AES256加密資料

『直接交易-Google Pay線下交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號 必填
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP 必填
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
data_json string(500) Google Pay線下資訊輸入(JSON格式) 『Google Pay線下資料』值參考
{
  "apiVersionMinor": 0,
  "apiVersion": 2,
  "paymentMethodData": {
    "description": "Visa •••• 1234",
    "tokenizationData": {
      "type": "PAYMENT_GATEWAY",
      "token": "{\"signature\":\"MEQCICA••••\\u003d\\u003d\",\"protocolVersion\":\"ECv1\",\"signedMessage\":\"{\\\"encryptedMessage\\\":\\\"2oGYBPrbBJIAg••••\\\\u003d\\\\u003d\\\",\\\"ephemeralPublicKey\\\":\\\"BOlRJqnD••••\\\\u003d\\\",\\\"tag\\\":\\\"g0lZC4••••\\\\u003d\\\"}\"}"
    },
    "type": "CARD",
    "info": {
      "cardNetwork": "VISA",
      "cardDetails": "1234"
    }
  }
}

『直接交易-Google Pay線下交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『Google Pay線下交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_state_msg string(500) 發票開立狀態訊息
invoice_date string(14) 發票開立日期(YYYYMMDDHHmmss)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string(50) 電子發票列印標題格式
invoice_print_type integer(1) 電子發票列印類型 『電子發票列印類型』值參考
invoice_print_device integer(1) 電子發票列印設備 『電子發票列印設備』值參考
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 電子發票開立類型-雲端發票類型 『雲端發票類型』值參考
invoice_mobile_code string(20) 當invoice_cloud_type為2時紀錄的手機條碼
invoice_tax_id string(8) 當invoice_cloud_type為2時紀錄的統一編號
invoice_natural_person string(20) 當invoice_cloud_type為3時紀錄的自然人憑證條碼
invoice_love_code string(20) 當invoice_input_type為2時紀錄的愛心碼
invoice_b2b_title string(50) 當invoice_input_type為3時紀錄的發票抬頭
invoice_b2b_id string(8) 當invoice_input_type為3時紀錄的統一編號
invoice_b2b_post_zone string(10) 當invoice_input_type為3時紀錄的郵遞區號
invoice_b2b_address string(200) 當invoice_input_type為3時紀錄的發票地址

悠遊付線下交易請求

消費者提供悠遊付支付碼供設備進行掃碼做交易動作。

因上游無提供測試資料,皆無法進行測試

<?php
/**
 * 經銷商串接-直接交易-悠遊付線下交易
 */
final class AgentEasywalletoff
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "A1234567891002";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "nq8KL8qNNCW12A3TBfAp4lU0y3PED8IQ";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "EASYWALLETOFF";
        $rawData['data_json'] = json_encode(['ewCode' => '99401096207398302106'], JSON_UNESCAPED_UNICODE);

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentEasywalletoff = new AgentEasywalletoff();
$AgentEasywalletoff->run();
?>
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-悠遊付線下
    /// </summary>
    public class AgentEasywalletoff {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "A1234567891002";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "nq8KL8qNNCW12A3TBfAp4lU0y3PED8IQ";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentEasywalletoff simulator = new AgentEasywalletoff();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";

            items.Add(item);

            dynamic JsonData = new ExpandoObject();
            JsonData.ewCode = "99401096207398302106";
            String DataJson = JsonConvert.SerializeObject(JsonData, Formatting.None);

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost = "10";
            rawData.user_id = "phper";
            rawData.order_id = "1234567890";
            rawData.ip = "127.0.0.1"; // 此為消費者IP,會做為驗證用
            rawData.pfn = "EASYWALLETOFF";
            rawData.data_json = DataJson;

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }
    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-悠遊付線下
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentEasywalletoff {
    /**
     * 經銷商商務代號
     */
    String agentUid = "A1234567891002";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "nq8KL8qNNCW12A3TBfAp4lU0y3PED8IQ";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentEasywalletoff simulator = new AgentEasywalletoff();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);

        Map<String, String> dataJson = new HashMap<>();
        dataJson.put("ewCode", "99401096207398302106");

        String data_json = "{}";

        try {
            ObjectMapper objMapper = new ObjectMapper();
            data_json = objMapper.writeValueAsString(dataJson);
        } catch (Exception e) {
            e.printStackTrace();
        }

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", "10");
        rawData.put("user_id", "phper");
        rawData.put("order_id", "1234567890");
        rawData.put("ip", "127.0.0.1"); // 此為消費者IP,會做為驗證用
        rawData.put("pfn", "EASYWALLETOFF");
        rawData.put("data_json", data_json);

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}
const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-悠遊付線下
 */
function AgentEasywalletoff() {
    // 經銷商商務代號
    this.agentUid = "A1234567891002";
    // 經銷商金鑰或認證碼
    this.agentKey = "nq8KL8qNNCW12A3TBfAp4lU0y3PED8IQ";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentEasywalletoff.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [{
            'id': "1",
            'name': "商品名稱",
            'cost': "10",
            'amount': "1",
            'total': "10"
        }],
        cost: "10",
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "EASYWALLETOFF",
        data_json: JSON.stringify({ewCode: '99401096207398302106'})
    };
};
/**
 * 取得服務位置
 */
AgentEasywalletoff.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentEasywalletoff.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentEasywalletoff.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentEasywalletoff.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentEasywalletoff.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentEasywalletoff = new AgentEasywalletoff();
AgentEasywalletoff.run();
# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-悠遊付線下交易
"""
class AgentEasywalletoff:
    # 經銷商商務代號
    agentUid = "518169081001";
    # 經銷商金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': 10,
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "EASYWALLETOFF",
            'data_json': "{\"ewCode\":\"99401096207398302106\"}",
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentEasywalletoff = AgentEasywalletoff()
AgentEasywalletoff.run()

回傳 JSON 結構如下:

{
    "code": "250",
    "msg": "執行成功。",
    "uid": 98432,
    "key": "7f8a2b459ae296a9d3fe8fffd0d7f8d2",
    "finishtime": "20211203114635",
    "cardno": "",
    "acode": "",
    "card_type": "0",
    "issuing_bank": "",
    "issuing_bank_uid": "",
    "transaction_mode": "1",
    "supplier_name": "悠遊付",
    "supplier_code": "W5",
    "order_id": "O20211203114630",
    "user_id": "phper",
    "cost": 10,
    "currency": "TWD",
    "actual_cost": 10,
    "actual_currency": "TWD",
    "pfn": "PXPAYOFF",
    "trans_type": 1,
    "result_type": 4,
    "result_content_type": "EASYWALLETOFF",
    "result_content": "{\n    \"Remark\": \"\",\n    \"TradeNo\": \"GR58745\",\n    \"OrderTotalCost\": \"100\",\n    \"InvoiceVehicle\": \"/ABD.122\",\n    \"CitizenDigitalCertificate\": \"\",\n    \"LoveCode\": \"\",\n    \"EventCode\": \"\",\n    \"PaymentType\": \"\",\n    \"DebitAmount\": \"100\"\n}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": "",
    "invoice_state": 0,
    "invoice_state_msg": "不處理",
    "invoice_date": "",
    "invoice_wordtrack": "",
    "invoice_number": "",
    "invoice_rand_code": "",
    "invoice_seller_ban": "",
    "invoice_buyer_ban": "",
    "invoice_left_qrcode": "",
    "invoice_middle_barcode": "",
    "invoice_right_qrcode": "",
    "invoice_title_type": 1,
    "invoice_title": "",
    "invoice_print_type": 0,
    "invoice_print_device": 0,
    "invoice_amount": "",
    "invoice_sales_amount": "",
    "invoice_tax_amount": "",
    "invoice_order_detail": "",
    "invoice_ratetype": 1,
    "invoice_input_type": 0,
    "invoice_cloud_type": 0,
    "invoice_mobile_code": "",
    "invoice_tax_id": "",
    "invoice_natural_person": "",
    "invoice_love_code": "",
    "invoice_b2b_title": "",
    "invoice_b2b_id": "",
    "invoice_b2b_post_zone": "",
    "invoice_b2b_address": ""
}

特約商店悠遊付線下交易參數說明

欄位 型態 說明
agent_uid string(16) 特約商店商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『悠遊付線下交易』欄位參考
JSON格式,AES256加密資料

『直接交易-悠遊付線下交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 『付款方式』值參考
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
data_json string(500) 悠遊付線下資訊輸入(JSON格式) 『悠遊付線下資料』值參考

『直接交易-悠遊付線下交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『悠遊付線下交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_state_msg string(500) 發票開立狀態訊息
invoice_date string(14) 發票開立日期(YYYYMMDDHHmmss)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string(50) 電子發票列印標題格式
invoice_print_type integer(1) 電子發票列印類型 『電子發票列印類型』值參考
invoice_print_device integer(1) 電子發票列印設備 『電子發票列印設備』值參考
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 電子發票開立類型-雲端發票類型 『雲端發票類型』值參考
invoice_mobile_code string(20) 當invoice_cloud_type為2時紀錄的手機條碼
invoice_tax_id string(8) 當invoice_cloud_type為2時紀錄的統一編號
invoice_natural_person string(20) 當invoice_cloud_type為3時紀錄的自然人憑證條碼
invoice_love_code string(20) 當invoice_input_type為2時紀錄的愛心碼
invoice_b2b_title string(50) 當invoice_input_type為3時紀錄的發票抬頭
invoice_b2b_id string(8) 當invoice_input_type為3時紀錄的統一編號
invoice_b2b_post_zone string(10) 當invoice_input_type為3時紀錄的郵遞區號
invoice_b2b_address string(200) 當invoice_input_type為3時紀錄的發票地址

支付寶線下交易請求

消費者提供支付寶支付碼供設備進行掃碼做交易動作。

因上游無提供測試資料,皆無法進行測試

<?php
/**
 * 經銷商串接-直接交易-支付寶線下
 */
final class AgentAlipayoff
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "A1234567891002";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "nq8KL8qNNCW12A3TBfAp4lU0y3PED8IQ";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "ALIPAYOFF";
        $rawData['data_json'] = json_encode(['alipayCode' => '134507721102798524'], JSON_UNESCAPED_UNICODE);

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentAlipayoff = new AgentAlipayoff();
$AgentAlipayoff->run();
?>
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-支付寶線下交易
    /// </summary>
    public class AgentAlipayoff {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentAlipayoff simulator = new AgentAlipayoff();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item1 = new ExpandoObject();
            item1.id = "1";
            item1.name = "商品名稱";
            item1.cost = "10";
            item1.amount = "1";
            item1.total = "10";
            items.Add(item1);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  10;
            rawData.user_id =  "phper";
            rawData.order_id =  "1234567890";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  "ALIPAYOFF";
            rawData.data_json =  "{\"alipayCode\":\"134507721102798524\"}";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }
    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-支付寶線下交易
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentAlipayoff {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentAlipayoff simulator = new AgentAlipayoff();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item1 = new HashMap<Object, Object>();
        item1.put("id", "1");
        item1.put("name", "商品名稱");
        item1.put("cost", "10");
        item1.put("amount", "1");
        item1.put("total", "10");
        items.add(item1);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", 10);
        rawData.put("user_id", "phper");
        rawData.put("order_id", "1234567890");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "ALIPAYOFF");
        rawData.put("data_json", "{\"alipayCode\":\"134507721102798524\"}");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-支付寶線下交易
 */
function AgentAlipayoff() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentAlipayoff.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [
                   {
                    'id': "1",
                    'name': "商品名稱",
                    'cost': "10",
                    'amount': "1",
                    'total': "10"
                   }
               ],
        cost: 10,
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "ALIPAYOFF",
        data_json: "{\"alipayCode\":\"134507721102798524\"}",

    };
};
/**
 * 取得服務位置
 */
AgentAlipayoff.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentAlipayoff.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentAlipayoff.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentAlipayoff.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentAlipayoff.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentAlipayoff = new AgentAlipayoff();
AgentAlipayoff.run();

# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-支付寶線下交易
"""
class AgentAlipayoff:
    # 經銷商商務代號
    agentUid = "518169081001";
    # 經銷商金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': 10,
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "ALIPAYOFF",
            'data_json': "{\"alipayCode\":\"134507721102798524\"}",
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentAlipayoff = AgentAlipayoff()
AgentAlipayoff.run()

回傳 JSON 結構如下:

{
    "invoice_state": 0,
    "invoice_state_msg": "不處理",
    "invoice_date": "",
    "invoice_wordtrack": "",
    "invoice_number": "",
    "invoice_rand_code": "",
    "invoice_seller_ban": "",
    "invoice_buyer_ban": "",
    "invoice_left_qrcode": "",
    "invoice_middle_barcode": "",
    "invoice_right_qrcode": "",
    "invoice_title_type": 1,
    "invoice_title": "",
    "invoice_print_type": 2,
    "invoice_print_device": 1,
    "invoice_amount": "",
    "invoice_sales_amount": "",
    "invoice_tax_amount": "",
    "invoice_order_detail": "",
    "invoice_ratetype": 1,
    "invoice_tax_rate": "",
    "invoice_input_type": 0,
    "invoice_cloud_type": 0,
    "invoice_mobile_code": "",
    "invoice_tax_id": "",
    "invoice_natural_person": "",
    "invoice_love_code": "",
    "invoice_b2b_title": "",
    "invoice_b2b_id": "",
    "invoice_b2b_post_zone": "",
    "invoice_b2b_address": "",
    "code": "300",
    "msg": "執行失敗,交易失敗,原因:。",
    "uid": 147393,
    "key": "b04eecddac77286ab9feafb1527032d6",
    "finishtime": "",
    "cardno": "",
    "acode": "",
    "card_type": "0",
    "issuing_bank": "",
    "issuing_bank_uid": "",
    "transaction_mode": "1",
    "supplier_name": "玉山銀行",
    "supplier_code": "B4",
    "order_id": "1234567890",
    "user_id": "phper",
    "cost": 10,
    "currency": "TWD",
    "actual_cost": 0,
    "actual_currency": "TWD",
    "pfn": "ALIPAYOFF",
    "trans_type": 1,
    "result_type": 4,
    "result_content_type": "ALIPAYOFF",
    "result_content": "{}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": "",
    "sys_echo": ""
}

經銷商『支付寶線下交易』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name":"api","cmd":"api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『支付寶線下交易』欄位參考
JSON格式,AES256加密資料

『支付寶線下交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 (ALIPAYOFF)
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_tax_rate float(5) 電子發票稅率:預設0.05(零稅與免稅帶0)
invoice_remark string(70) 發票註記(依加值中心提供註記功能)
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
data_json string(500) 支付寶線下資訊輸入(JSON格式) 『支付寶線下資料』值參考

『支付寶線下交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『支付寶線下交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_state_msg string(500) 發票開立狀態訊息
invoice_date string(14) 發票開立日期(YYYYMMDDHHmmss)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string(50) 電子發票列印標題格式
invoice_print_type integer(1) 電子發票列印類型 『電子發票列印類型』值參考
invoice_print_device integer(1) 電子發票列印設備 『電子發票列印設備』值參考
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_tax_rate float(5) 電子發票稅率:預設0.05(零稅與免稅帶0)
invoice_remark string(70) 發票註記(依加值中心提供註記功能)
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 電子發票開立類型-雲端發票類型 『雲端發票類型』值參考
invoice_mobile_code string(20) 當invoice_cloud_type為2時紀錄的手機條碼
invoice_tax_id string(8) 當invoice_cloud_type為2時紀錄的統一編號
invoice_natural_person string(20) 當invoice_cloud_type為3時紀錄的自然人憑證條碼
invoice_love_code string(20) 當invoice_input_type為2時紀錄的愛心碼
invoice_b2b_title string(50) 當invoice_input_type為3時紀錄的發票抬頭
invoice_b2b_id string(8) 當invoice_input_type為3時紀錄的統一編號
invoice_b2b_post_zone string(10) 當invoice_input_type為3時紀錄的郵遞區號
invoice_b2b_address string(200) 當invoice_input_type為3時紀錄的發票地址

全盈支付線上交易

商家發動後會根據回應資料內容result_content中,依據使用裝置,開啟相對應的連結

因上游無提供測試資料,皆無法進行測試

<?php
/**
 * 經銷商串接-全盈支付線上交易
 */
final class AgentPluspayon
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880011";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "http://pay.k20-mypay.tw/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [
                                [
                                 'id' => '1',
                                 'name' => '商品名稱',
                                 'cost' => '10',
                                 'amount' => '1',
                                 'total' => '10'
                                ]
                            ];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "O20240618120110";
        $rawData['ip'] = "127.0.0.1";
        $rawData['pfn'] = "PLUSPAYON";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentPluspayon = new AgentPluspayon();
$AgentPluspayon->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-全盈支付線上交易
    /// </summary>
    public class AgentPluspayon {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880011";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "http://pay.k20-mypay.tw/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentPluspayon simulator = new AgentPluspayon();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item1 = new ExpandoObject();
            item1.id = "1";
            item1.name = "商品名稱";
            item1.cost = "10";
            item1.amount = "1";
            item1.total = "10";
            items.Add(item1);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  10;
            rawData.user_id =  "phper";
            rawData.order_id =  "O20240618120110";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  "PLUSPAYON";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }
    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-全盈支付線上交易
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentPluspayon {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880011";
    /**
     * 串接交易位置
     */
    String url = "http://pay.k20-mypay.tw/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentPluspayon simulator = new AgentPluspayon();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item1 = new HashMap<Object, Object>();
        item1.put("id", "1");
        item1.put("name", "商品名稱");
        item1.put("cost", "10");
        item1.put("amount", "1");
        item1.put("total", "10");
        items.add(item1);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", 10);
        rawData.put("user_id", "phper");
        rawData.put("order_id", "O20240618120110");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "PLUSPAYON");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-全盈支付線上交易
 */
function AgentPluspayon() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    // 特約商店商務代號
    this.storeUid = "289151880011";
    // 串接交易位置
    this.url = "http://pay.k20-mypay.tw/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentPluspayon.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [
                   {
                    'id': "1",
                    'name': "商品名稱",
                    'cost': "10",
                    'amount': "1",
                    'total': "10"
                   }
               ],
        cost: 10,
        user_id: "phper",
        order_id: "O20240618120110",
        ip: "127.0.0.1",
        pfn: "PLUSPAYON",

    };
};
/**
 * 取得服務位置
 */
AgentPluspayon.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentPluspayon.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentPluspayon.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentPluspayon.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentPluspayon.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentPluspayon = new AgentPluspayon();
AgentPluspayon.run();

# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-全盈支付線上交易
"""
class AgentPluspayon:
    # 經銷商商務代號
    agentUid = "518169081001";
    # 經銷商金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    # 特約商店商務代號
    storeUid = "289151880011"
    # 串接交易位置
    url = "http://pay.k20-mypay.tw/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': 10,
            'user_id': "phper",
            'order_id': "O20240618120110",
            'ip': "127.0.0.1",
            'pfn': "PLUSPAYON",
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentPluspayon = AgentPluspayon()
AgentPluspayon.run()

回傳 JSON 結構如下:

{
    "invoice_state": 0,
    "invoice_state_msg": "不處理",
    "invoice_date": "",
    "invoice_wordtrack": "",
    "invoice_number": "",
    "invoice_rand_code": "",
    "invoice_seller_ban": "",
    "invoice_seller_name": "",
    "invoice_buyer_ban": "",
    "invoice_buyer_name": "",
    "invoice_left_qrcode": "",
    "invoice_middle_barcode": "",
    "invoice_right_qrcode": "",
    "invoice_title_type": 1,
    "invoice_title": "",
    "invoice_print_type": 2,
    "invoice_print_device": 1,
    "invoice_amount": "",
    "invoice_sales_amount": "",
    "invoice_tax_amount": "",
    "invoice_order_detail": "",
    "invoice_ratetype": 1,
    "invoice_tax_rate": "",
    "invoice_remark": "",
    "invoice_input_type": 0,
    "invoice_cloud_type": 0,
    "invoice_mobile_code": "",
    "invoice_tax_id": "",
    "invoice_tax_title": "",
    "invoice_natural_person": "",
    "invoice_m_post_zone": "",
    "invoice_m_address": "",
    "invoice_love_code": "",
    "invoice_b2b_title": "",
    "invoice_b2b_id": "",
    "invoice_b2b_post_zone": "",
    "invoice_b2b_address": "",
    "code": "280",
    "msg": "執行成功。",
    "uid": 194591,
    "key": "68d2a09c31643660f29172d80dbaf9ef",
    "finishtime": "",
    "cardno": "",
    "acode": "",
    "card_type": "0",
    "issuing_bank": "",
    "issuing_bank_uid": "",
    "is_agent_charge": 0,
    "transaction_mode": "1",
    "supplier_name": "全盈支付",
    "supplier_code": "W8",
    "order_id": "O20240618120152",
    "user_id": "phper",
    "cost": 10,
    "currency": "TWD",
    "actual_cost": 0,
    "actual_currency": "TWD",
    "pfn": "PLUSPAYON",
    "actual_pay_mode": "",
    "trans_type": 1,
    "result_type": 4,
    "result_content_type": "PLUSPAYON",
    "result_content": "{\"Web\":\"https:\\/\\/qr-uat.pluspay.com.tw\\/ABBOQhmtUo\"}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": "",
    "sys_echo": ""
}

經銷商『全盈支付線上交易』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name":"api","cmd":"api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『全盈支付線上交易』欄位參考
JSON格式,AES256加密資料

『全盈支付線上交易』欄位

參數名稱 型態 說明 必須
store_uid string 特約商店代碼 必填
cost string 訂單總金額 必填
currency string 預設交易幣別(預設為TWD新台幣)
order_id string 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string 自訂回傳參數 1
echo_1 string 自訂回傳參數 2
echo_2 string 自訂回傳參數 3
echo_3 string 自訂回傳參數 4
echo_4 string 自訂回傳參數 5
pfn string 付費方法 (PLUSPAYON) 必填
discount string 折價金額 (預設0)
shipping_fee string 運費
user_id string 消費者帳號
user_name string 消費者姓名
user_real_name string 消費者真實姓名
user_english_name string 消費者英文名稱
user_zipcode string 消費者郵遞區號
user_address string 消費者地址
user_sn_type string 證號類型 『證號類型』值參考
user_sn string 付款人身分證/統一證號/護照號碼
user_phone string 消費者家用電話
user_cellphone_code string 消費者行動電話國碼
user_cellphone string 消費者行動電話
user_email string 消費者 E-Mail
user_birthday string 消費者生日
ip string 消費者來源 IP
issue_invoice_state integer 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer 電子發票稅率別 『電子發票稅率別』值參考
invoice_tax_rate float 電子發票稅率:預設0.05(零稅與免稅帶0)
invoice_remark string 發票註記(依加值中心提供註記功能)
invoice_input_type integer 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_m_post_zone string EMail 紙本寄送郵遞區號 當invoice_cloud_type為4,此欄位才有效,非必須
invoice_m_address string EMail 紙本寄送住址 當invoice_cloud_type為4,此欄位才有效,非必須
invoice_love_code string 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string 發票地址 當invoice_input_type為3時,此欄位才有效
interface string 消費者操作介面類型 pc/app
agent_sms_fee_type integer 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string 經銷商代收費
is_agent_charge integer 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考

『全盈支付線上交易』回傳欄位

參數名稱 型態 說明 必須
code string 交易狀態代碼
msg string 回傳訊息
uid string Payment Hub之交易流水號
key string 交易驗証碼
finishtime string 交易完成時間(YYYYMMDDHHmmss)
cardno string 銀行端口回傳碼
acode string 授權碼
card_type integer 信用卡卡別 『信用卡別類型』值參考
issuing_bank string 發卡行
issuing_bank_uid string 發卡銀行代碼
is_agent_charge int 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer 交易服務類型 『交易服務類型』值參考
supplier_name string 交易之金融服務商
supplier_code string 交易之金融服務商代碼
order_id string 貴特店系統的訂單編號
user_id string 消費者帳號
cost string 總交易金額
currency string 原交易幣別
actual_cost string 實際交易金額
actual_currency string 實際交易幣別
pfn string 付費方法 『回傳付款方式』值參考
actual_pay_mode string 實際支付方式
(當pfn為CASH-自行收款時,告知系統實際收款方式)
『自行收款付款方式』值參考
trans_type integer 交易類型 『交易類型定義』值參考
result_type string 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string 回傳結果 『全盈支付線上交易回傳欄位』值參考
echo_0 string 自訂回傳參數 1
echo_1 string 自訂回傳參數 2
echo_2 string 自訂回傳參數 3
echo_3 string 自訂回傳參數 4
echo_4 string 自訂回傳參數 5
invoice_state integer 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_state_msg string 發票開立狀態訊息
invoice_date string 發票開立日期(YYYYMMDDHHmmss)
invoice_wordtrack string 發票字軌
invoice_number string 發票號碼
invoice_rand_code string 電子發票隨機碼
invoice_seller_ban string 賣方統一編號
invoice_seller_name string 賣方名稱
invoice_buyer_ban string 買方統一編號
invoice_buyer_name string 買方名稱
invoice_left_qrcode string 電子發票左邊QrCode內容
invoice_middle_barcode string 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string 電子發票右邊QrCode內容
invoice_title_type integer 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string 電子發票列印標題格式
invoice_print_type integer 電子發票列印類型 『電子發票列印類型』值參考
invoice_print_device integer 電子發票列印設備 『電子發票列印設備』值參考
invoice_amount string 電子發票銷售總額
invoice_sales_amount string 電子發票銷售額
invoice_tax_amount string 電子發票稅額
invoice_order_detail string 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer 電子發票稅率別 『電子發票稅率別』值參考
invoice_tax_rate float 電子發票稅率:預設0.05(零稅與免稅帶0)
invoice_remark string 發票註記(依加值中心提供註記功能)
invoice_input_type integer 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer 電子發票開立類型-雲端發票類型 『雲端發票類型』值參考
invoice_mobile_code string 當invoice_cloud_type為2時紀錄的手機條碼
invoice_tax_id string 當invoice_cloud_type為2時紀錄的統一編號
invoice_tax_title string 當invoice_cloud_type為2時紀錄的買受人公司名稱
invoice_natural_person string 當invoice_cloud_type為3時紀錄的自然人憑證條碼
invoice_m_post_zone string 當invoice_cloud_type為4時紀錄中獎時紙本發票郵遞區號
invoice_m_address string 當invoice_cloud_type為4時紀錄中獎時紙本發票收件住址
invoice_love_code string 當invoice_input_type為2時紀錄的愛心碼
invoice_b2b_title string 當invoice_input_type為3時紀錄的發票抬頭
invoice_b2b_id string 當invoice_input_type為3時紀錄的統一編號
invoice_b2b_post_zone string 當invoice_input_type為3時紀錄的郵遞區號
invoice_b2b_address string 當invoice_input_type為3時紀錄的發票地址

全盈支付線下交易請求

消費者提供全盈支付支付碼供設備進行掃碼做交易動作。

因上游無提供測試資料,皆無法進行測試

<?php
/**
 * 經銷商串接-直接交易-全盈支付線下
 */
final class AgentPluspayoff
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "A1234567891002";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "nq8KL8qNNCW12A3TBfAp4lU0y3PED8IQ";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "PLUSPAYOFF";
        $rawData['data_json'] = json_encode(['plusCode' => 'FP372E9AGSAI9OJNRW'], JSON_UNESCAPED_UNICODE);

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentPluspayoff = new AgentPluspayoff();
$AgentPluspayoff->run();
?>
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-全盈支付線下交易
    /// </summary>
    public class AgentPluspayoff {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentPluspayoff simulator = new AgentPluspayoff();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item1 = new ExpandoObject();
            item1.id = "1";
            item1.name = "商品名稱";
            item1.cost = "10";
            item1.amount = "1";
            item1.total = "10";
            items.Add(item1);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  10;
            rawData.user_id =  "phper";
            rawData.order_id =  "1234567890";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  "PLUSPAYOFF";
            rawData.data_json =  "{\"plusCode\":\"134507721102798524\"}";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }
    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-全盈支付線下交易
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentPluspayoff {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentPluspayoff simulator = new AgentPluspayoff();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item1 = new HashMap<Object, Object>();
        item1.put("id", "1");
        item1.put("name", "商品名稱");
        item1.put("cost", "10");
        item1.put("amount", "1");
        item1.put("total", "10");
        items.add(item1);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", 10);
        rawData.put("user_id", "phper");
        rawData.put("order_id", "1234567890");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "PLUSPAYOFF");
        rawData.put("data_json", "{\"plusCode\":\"134507721102798524\"}");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-全盈支付線下交易
 */
function AgentPluspayoff() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentPluspayoff.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [
                   {
                    'id': "1",
                    'name': "商品名稱",
                    'cost': "10",
                    'amount': "1",
                    'total': "10"
                   }
               ],
        cost: 10,
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: "PLUSPAYOFF",
        data_json: "{\"plusCode\":\"134507721102798524\"}",

    };
};
/**
 * 取得服務位置
 */
AgentPluspayoff.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentPluspayoff.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentPluspayoff.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentPluspayoff.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentPluspayoff.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentPluspayoff = new AgentPluspayoff();
AgentPluspayoff.run();

# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-全盈支付線下交易
"""
class AgentPluspayoff:
    # 經銷商商務代號
    agentUid = "518169081001";
    # 經銷商金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': 10,
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': "PLUSPAYOFF",
            'data_json': "{\"plusCode\":\"134507721102798524\"}",
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentPluspayoff = AgentPluspayoff()
AgentPluspayoff.run()

回傳 JSON 結構如下:

{
    "invoice_state": 0,
    "invoice_state_msg": "不處理",
    "invoice_date": "",
    "invoice_wordtrack": "",
    "invoice_number": "",
    "invoice_rand_code": "",
    "invoice_seller_ban": "",
    "invoice_buyer_ban": "",
    "invoice_left_qrcode": "",
    "invoice_middle_barcode": "",
    "invoice_right_qrcode": "",
    "invoice_title_type": 1,
    "invoice_title": "",
    "invoice_print_type": 2,
    "invoice_print_device": 1,
    "invoice_amount": "",
    "invoice_sales_amount": "",
    "invoice_tax_amount": "",
    "invoice_order_detail": "",
    "invoice_ratetype": 1,
    "invoice_tax_rate": "",
    "invoice_input_type": 0,
    "invoice_cloud_type": 0,
    "invoice_mobile_code": "",
    "invoice_tax_id": "",
    "invoice_natural_person": "",
    "invoice_love_code": "",
    "invoice_b2b_title": "",
    "invoice_b2b_id": "",
    "invoice_b2b_post_zone": "",
    "invoice_b2b_address": "",
    "code": "300",
    "msg": "執行失敗,交易失敗,原因:。",
    "uid": 147393,
    "key": "b04eecddac77286ab9feafb1527032d6",
    "finishtime": "",
    "cardno": "",
    "acode": "",
    "card_type": "0",
    "issuing_bank": "",
    "issuing_bank_uid": "",
    "transaction_mode": "1",
    "supplier_name": "玉山銀行",
    "supplier_code": "B4",
    "order_id": "1234567890",
    "user_id": "phper",
    "cost": 10,
    "currency": "TWD",
    "actual_cost": 0,
    "actual_currency": "TWD",
    "pfn": "PLUSPAYOFF",
    "trans_type": 1,
    "result_type": 4,
    "result_content_type": "PLUSPAYOFF",
    "result_content": "{}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": "",
    "sys_echo": ""
}

經銷商『全盈支付線下交易』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name":"api","cmd":"api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『全盈支付線下交易』欄位參考
JSON格式,AES256加密資料

『全盈支付線下交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 (PLUSPAYOFF)
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_tax_rate float(5) 電子發票稅率:預設0.05(零稅與免稅帶0)
invoice_remark string(70) 發票註記(依加值中心提供註記功能)
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
data_json string(500) 全盈支付線下資訊輸入(JSON格式) 『全盈支付線下資料』值參考

『全盈支付線下交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『全盈支付線下交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_state_msg string(500) 發票開立狀態訊息
invoice_date string(14) 發票開立日期(YYYYMMDDHHmmss)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string(50) 電子發票列印標題格式
invoice_print_type integer(1) 電子發票列印類型 『電子發票列印類型』值參考
invoice_print_device integer(1) 電子發票列印設備 『電子發票列印設備』值參考
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_tax_rate float(5) 電子發票稅率:預設0.05(零稅與免稅帶0)
invoice_remark string(70) 發票註記(依加值中心提供註記功能)
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 電子發票開立類型-雲端發票類型 『雲端發票類型』值參考
invoice_mobile_code string(20) 當invoice_cloud_type為2時紀錄的手機條碼
invoice_tax_id string(8) 當invoice_cloud_type為2時紀錄的統一編號
invoice_natural_person string(20) 當invoice_cloud_type為3時紀錄的自然人憑證條碼
invoice_love_code string(20) 當invoice_input_type為2時紀錄的愛心碼
invoice_b2b_title string(50) 當invoice_input_type為3時紀錄的發票抬頭
invoice_b2b_id string(8) 當invoice_input_type為3時紀錄的統一編號
invoice_b2b_post_zone string(10) 當invoice_input_type為3時紀錄的郵遞區號
invoice_b2b_address string(200) 當invoice_input_type為3時紀錄的發票地址

錢包被掃交易

消費者提供支付碼供設備進行掃碼做交易動作。(支援自動辨識MYPAY電子錢包、Pi 拍錢包、LINE Pay、街口支付、WeChat Pay、支付宝、悠遊付、全支付、全盈支付)

<?php
/**
 * 經銷商串接-錢包被掃交易
 */
final class AgentOffline
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "2MrhtRYeF9wKZ4bKwzZoL8aZf26pWzIG";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [
                                [
                                 'id' => '1',
                                 'name' => '商品名稱',
                                 'cost' => '10',
                                 'amount' => '1',
                                 'total' => '10'
                                ]
                            ];
        $rawData['cost'] = "10";
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1";
        $rawData['pfn'] = 98;
        $rawData['data_json'] = "{\"qrCode\":\"MY13697573pbmQsYhY\"}";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentOffline = new AgentOffline();
$AgentOffline->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-錢包被掃交易
    /// </summary>
    public class AgentOffline {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "2MrhtRYeF9wKZ4bKwzZoL8aZf26pWzIG";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentOffline simulator = new AgentOffline();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";
            items.Add(item);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  "10";
            rawData.user_id =  "phper";
            rawData.order_id =  "1234567890";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  98;
            rawData.data_json =  "{\"qrCode\":\"MY13697573pbmQsYhY\"}";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }
    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-錢包被掃交易
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentOffline {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "2MrhtRYeF9wKZ4bKwzZoL8aZf26pWzIG";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentOffline simulator = new AgentOffline();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", "10");
        rawData.put("user_id", "phper");
        rawData.put("order_id", "1234567890");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", 98);
        rawData.put("data_json", "{\"qrCode\":\"MY13697573pbmQsYhY\"}");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-錢包被掃交易
 */
function AgentOffline() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 經銷商金鑰或認證碼
    this.agentKey = "2MrhtRYeF9wKZ4bKwzZoL8aZf26pWzIG";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentOffline.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        items: [
                   {
                    'id': "1",
                    'name': "商品名稱",
                    'cost': "10",
                    'amount': "1",
                    'total': "10"
                   }
               ],
        cost: "10",
        user_id: "phper",
        order_id: "1234567890",
        ip: "127.0.0.1",
        pfn: 98,
        data_json: "{\"qrCode\":\"MY13697573pbmQsYhY\"}",

    };
};
/**
 * 取得服務位置
 */
AgentOffline.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/transaction"
    };
};
/**
 * AES 256 加密
 */
AgentOffline.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentOffline.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentOffline.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentOffline.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentOffline = new AgentOffline();
AgentOffline.run();

# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-錢包被掃交易
"""
class AgentOffline:
    # 經銷商商務代號
    agentUid = "518169081001";
    # 經銷商金鑰或認證碼
    agentKey = b"2MrhtRYeF9wKZ4bKwzZoL8aZf26pWzIG";
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': "10",
            'user_id': "phper",
            'order_id': "1234567890",
            'ip': "127.0.0.1",
            'pfn': 98,
            'data_json': "{\"qrCode\":\"MY13697573pbmQsYhY\"}",
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentOffline = AgentOffline()
AgentOffline.run()

回傳 JSON 結構如下:

{
    "invoice_state": 0,
    "invoice_state_msg": "不處理",
    "invoice_date": "",
    "invoice_wordtrack": "",
    "invoice_number": "",
    "invoice_rand_code": "",
    "invoice_seller_ban": "",
    "invoice_buyer_ban": "",
    "invoice_left_qrcode": "",
    "invoice_middle_barcode": "",
    "invoice_right_qrcode": "",
    "invoice_title_type": 1,
    "invoice_title": "",
    "invoice_print_type": 2,
    "invoice_print_device": 1,
    "invoice_amount": "",
    "invoice_sales_amount": "",
    "invoice_tax_amount": "",
    "invoice_order_detail": "",
    "invoice_ratetype": 1,
    "invoice_tax_rate": "",
    "invoice_input_type": 0,
    "invoice_cloud_type": 0,
    "invoice_mobile_code": "",
    "invoice_tax_id": "",
    "invoice_natural_person": "",
    "invoice_love_code": "",
    "invoice_b2b_title": "",
    "invoice_b2b_id": "",
    "invoice_b2b_post_zone": "",
    "invoice_b2b_address": "",
    "code": "300",
    "msg": "執行失敗,並未將物件參考設定為物件的執行個體。",
    "uid": 147394,
    "key": "8a956d21964aca9ed1a52dd08fb61173",
    "finishtime": "",
    "cardno": "",
    "acode": "",
    "card_type": "0",
    "issuing_bank": "",
    "issuing_bank_uid": "",
    "transaction_mode": "1",
    "supplier_name": "華泰銀行",
    "supplier_code": "BE",
    "order_id": "1234567890",
    "user_id": "phper",
    "cost": 10,
    "currency": "TWD",
    "actual_cost": 0,
    "actual_currency": "TWD",
    "pfn": "TWPAYOFF",
    "trans_type": 1,
    "result_type": 4,
    "result_content_type": "TWPAYOFF",
    "result_content": "{}",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": "",
    "sys_echo": ""
}

經銷商『錢包被掃交易』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name":"api","cmd":"api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『錢包被掃交易』欄位參考
JSON格式,AES256加密資料

『錢包被掃交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法 (OFFLINE)
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_tax_rate float(5) 電子發票稅率:預設0.05(零稅與免稅帶0)
invoice_remark string(70) 發票註記(依加值中心提供註記功能)
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
data_json string(500) 錢包被掃交易資訊輸入(JSON格式) 『錢包被掃交易資料』值參考

『錢包被掃交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『全支付線下交易回傳欄位』值參考
『支付寶線下交易回傳欄位』值參考
『悠遊付線下交易回傳欄位』值參考
『Pi錢包線下交易回傳欄位』值參考
『街口支付線下交易回傳欄位』值參考
『LINE Pay線下交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_state_msg string(500) 發票開立狀態訊息
invoice_date string(14) 發票開立日期(YYYYMMDDHHmmss)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string(50) 電子發票列印標題格式
invoice_print_type integer(1) 電子發票列印類型 『電子發票列印類型』值參考
invoice_print_device integer(1) 電子發票列印設備 『電子發票列印設備』值參考
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_tax_rate float(5) 電子發票稅率:預設0.05(零稅與免稅帶0)
invoice_remark string(70) 發票註記(依加值中心提供註記功能)
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 電子發票開立類型-雲端發票類型 『雲端發票類型』值參考
invoice_mobile_code string(20) 當invoice_cloud_type為2時紀錄的手機條碼
invoice_tax_id string(8) 當invoice_cloud_type為2時紀錄的統一編號
invoice_natural_person string(20) 當invoice_cloud_type為3時紀錄的自然人憑證條碼
invoice_love_code string(20) 當invoice_input_type為2時紀錄的愛心碼
invoice_b2b_title string(50) 當invoice_input_type為3時紀錄的發票抬頭
invoice_b2b_id string(8) 當invoice_input_type為3時紀錄的統一編號
invoice_b2b_post_zone string(10) 當invoice_input_type為3時紀錄的郵遞區號
invoice_b2b_address string(200) 當invoice_input_type為3時紀錄的發票地址

自行收款交易

商店自行向消費者收款時,可發動此交易請求,將收款記錄在MYPAY。

<?php
/**
 * 經銷商串接-直接交易-自行收款交易
 */
final class AgentCash
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['items'] = [['id' => '1',
            'name' => '商品名稱',
            'cost' => '10',
            'amount' => '1',
            'total' => '10']];
        $rawData['cost'] = 10;
        $rawData['user_id'] = "phper";
        $rawData['order_id'] = "1234567890";
        $rawData['ip'] = "127.0.0.1"; // 此為消費者IP,會做為驗證用
        $rawData['pfn'] = "CASH";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/transaction'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentCash = new AgentCash();
$AgentCash->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易-自行收款交易
    /// </summary>
    public class AgentCash {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentCash simulator = new AgentCash();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "商品名稱";
            item.cost = "10";
            item.amount = "1";
            item.total = "10";
            items.Add(item);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.items = items;
            rawData.cost =  10;
            rawData.user_id =  "phper";
            rawData.order_id =  "O20211203114630";
            rawData.ip =  "127.0.0.1";
            rawData.pfn =  "CASH";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/transaction";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}


import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易-自行收款交易
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentCash {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentCash simulator = new AgentCash();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "商品名稱");
        item.put("cost", "10");
        item.put("amount", "1");
        item.put("total", "10");
        items.add(item);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("items", items);
        rawData.put("cost", 10);
        rawData.put("user_id", "phper");
        rawData.put("order_id", "O20211203114630");
        rawData.put("ip", "127.0.0.1");
        rawData.put("pfn", "CASH");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/transaction");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}


const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易-自行收款交易
 */
function AgentCash() {
  // 特約商店商務代號
  this.agentUid = "518169081001";
  // 特約商店金鑰或認證碼
  this.agentKey = "KYTjd9ACcjGaTK6V3zWmMkyrQS08Ndcx";
  // 串接交易位置
  this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentCash.prototype.getRawData = function () {
  return {
    store_uid: this.storeUid,
    items: [
      {
        'id': "1",
        'name': "商品名稱",
        'cost': "10",
        'amount': "1",
        'total': "10"
      }
    ],
    cost: 10,
    user_id: "phper",
    order_id: "O20211203114630",
    ip: "127.0.0.1",
    pfn: "CASH",

  };
};
/**
 * 取得服務位置
 */
AgentCash.prototype.getService = function () {
  return {
    service_name: "api",
    cmd: "api/transaction"
  };
};
/**
 * AES 256 加密
 */
AgentCash.prototype.encrypt = function (fields, key) {
  let eData = JSON.stringify(fields);
  const blockSize = 16;
  const iv = crypto.randomBytes(blockSize);
  const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
  let tmpCipher = encryptor.update(Buffer.from(eData));
  let finalCipher = encryptor.final();
  const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
  let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
  return data;
};
/**
 * 資料 POST 到主機
 */
AgentCash.prototype.post = function (postData) {
  return new Promise((res, rej) => {
    let options = {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      rejectUnauthorized: false
    };

    let send_process = httpRequest.request(this.url, options, (api_res) => {
      let res_data = "";
      api_res.on('data', (tmp_data) => {
        res_data += tmp_data;
      });
      api_res.on('end', () => {
        res(res_data);
      });
    });

    send_process.write(JSON.stringify(postData));
    send_process.end();
  });
};
/**
 * 取得送出欄位資料
 */
AgentCash.prototype.getPostData = function () {
  return {
    "agent_uid": this.agentUid,
    "service": this.encrypt(this.getService(), this.agentKey),
    "encry_data": this.encrypt(this.getRawData(), this.agentKey)
  };
};
/**
 * 執行
 */
AgentCash.prototype.run = async function () {
  json = await this.post(this.getPostData())
  console.log(json);
};

AgentCash = new AgentCash();
AgentCash.run();


# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易-自行收款交易
"""
class AgentCash:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'items': [
                         {
                          'id': "1",
                          'name': "商品名稱",
                          'cost': "10",
                          'amount': "1",
                          'total': "10"
                         }
                     ],
            'cost': 10,
            'user_id': "phper",
            'order_id': "O20211203114630",
            'ip': "127.0.0.1",
            'pfn': "CASH",
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/transaction'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentCash = AgentCash()
AgentCash.run()


回傳 JSON 結構如下:

{
  "code": "250",
  "msg": "執行成功。",
  "uid": 106991,
  "key": "50306bf7def7cd1d37788558ed253259",
  "finishtime": "20220422143522",
  "cardno": "",
  "acode": "",
  "card_type": "0",
  "issuing_bank": "",
  "issuing_bank_uid": "",
  "transaction_mode": "2",
  "supplier_name": "高鉅科技",
  "supplier_code": "T0",
  "order_id": "1234567890",
  "user_id": "phper",
  "cost": 10,
  "currency": "TWD",
  "actual_cost": 10,
  "actual_currency": "TWD",
  "pfn": "CASH",
  "trans_type": 1,
  "result_type": 4,
  "result_content_type": "CASH",
  "result_content": "{\n    \"OrderTotalCost\": 10,\n    \"TradeDate\": \"20220422143522\"\n}",
  "echo_0": "",
  "echo_1": "",
  "echo_2": "",
  "echo_3": "",
  "echo_4": "",
  "invoice_state": 0,
  "invoice_state_msg": "不處理",
  "invoice_date": "",
  "invoice_wordtrack": "",
  "invoice_number": "",
  "invoice_rand_code": "",
  "invoice_seller_ban": "",
  "invoice_buyer_ban": "",
  "invoice_left_qrcode": "",
  "invoice_middle_barcode": "",
  "invoice_right_qrcode": "",
  "invoice_title_type": 1,
  "invoice_title": "",
  "invoice_print_type": 0,
  "invoice_print_device": 0,
  "invoice_amount": "",
  "invoice_sales_amount": "",
  "invoice_tax_amount": "",
  "invoice_order_detail": "",
  "invoice_ratetype": 1,
  "invoice_input_type": 0,
  "invoice_cloud_type": 0,
  "invoice_mobile_code": "",
  "invoice_tax_id": "",
  "invoice_natural_person": "",
  "invoice_love_code": "",
  "invoice_b2b_title": "",
  "invoice_b2b_id": "",
  "invoice_b2b_post_zone": "",
  "invoice_b2b_address": ""
}

經銷商自行收款交易參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/transaction"}
JSON格式,AES256加密資料
encry_data text 『自行收款交易』欄位參考
JSON格式,AES256加密資料

『直接交易-自行收款交易』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店代碼 必填
cost string(19) 訂單總金額 必填
currency string(10) 預設交易幣別(預設為TWD新台幣)
order_id string(50) 訂單編號 必填
items array 訂單內物品數 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
pfn string(20) 付費方法(請帶字串CASH)
discount string(19) 折價金額 (預設0)
shipping_fee string(19) 運費
user_id string(50) 消費者帳號 必填
user_name string(20) 消費者姓名
user_real_name string(20) 消費者真實姓名
user_english_name string(50) 消費者英文名稱
user_zipcode string(10) 消費者郵遞區號
user_address string(255) 消費者地址
user_sn_type string(1) 證號類型 『證號類型』值參考
user_sn string(19) 付款人身分證/統一證號/護照號碼
user_phone string(20) 消費者家用電話
user_cellphone_code string(6) 消費者行動電話國碼
user_cellphone string(20) 消費者行動電話
user_email string(80) 消費者 E-Mail
user_birthday string(10) 消費者生日
ip string(50) 消費者來源 IP 必填
issue_invoice_state integer(1) 開立發票 『電子發票是否開立狀態』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 「雲端發票」類型 當invoice_input_type為1,此狀態才有效
『雲端發票類型』值參考
invoice_tax_id string(8) 統一編號 當invoice_input_type為1,此欄位才有效,非必要
invoice_mobile_code string(20) 手機條碼 當invoice_cloud_type為2,此欄位才有效
invoice_natural_person string(20) 自然人憑證條碼 當invoice_cloud_type為3,此欄位才有效
invoice_love_code string(20) 愛心碼 當invoice_input_type為2,此欄位才有效
invoice_b2b_title string(50) 發票抬頭 當invoice_input_type為3時,此欄位才有效
invoice_b2b_id string(8) 統一編號 當invoice_input_type為3時,此欄位才有效
invoice_b2b_post_zone string(10) 發票郵遞區號 當invoice_input_type為3時,此欄位才有效,非必須
invoice_b2b_address string(200) 發票地址 當invoice_input_type為3時,此欄位才有效
agent_sms_fee_type integer(1) 經銷商代收費是否含簡訊費 (0.不含 1.含) 『含不含簡訊費』值參考
agent_charge_fee_type integer(1) 經銷商代收費是否含手續費 (0.不含 1.含) 『含不含手續費類型』值參考
agent_charge_fee string(9) 經銷商代收費
is_agent_charge integer(1) 是否為經銷商代收費模式
若 is_agent_charge 有指定,以指定優先
若欄位agent_charge_fee有費用,或經銷商代收費是含簡訊費、或經銷商代收費含手續費,則預設為1
若欄位agent_charge_fee無費用,且經銷商代收費不含簡訊費、或經銷商代收費不含手續費或參欄位都未使用則預設為0
『是否為經銷商代收費模式』值參考
actual_pay_mode string(20) 實際支付方式
(當pfn為CASH-自行收款時,告知系統實際收款方式)
『自行收款付款方式』值參考

『直接交易-自行收款交易』回傳欄位

參數名稱 型態 說明 必須
code string(10) 交易狀態代碼
msg string(500) 回傳訊息
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type integer(1) 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
pfn string(20) 付費方法 『回傳付款方式』值參考
actual_pay_mode string(20) 實際支付方式
(當pfn為CASH-自行收款時,告知系統實際收款方式)
『自行收款付款方式』值參考
trans_type integer(1) 交易類型 『交易類型定義』值參考
result_type string(2) 回傳結果資料類型 『閘道內容回傳格式類型』值參考
result_content_type string(20) 回傳資料內容類型 『資料內容所屬支付名稱』值參考
result_content string(1000) 回傳結果 『自行收款交易回傳欄位』值參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_state_msg string(500) 發票開立狀態訊息
invoice_date string(14) 發票開立日期(YYYYMMDDHHmmss)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string(50) 電子發票列印標題格式
invoice_print_type integer(1) 電子發票列印類型 『電子發票列印類型』值參考
invoice_print_device integer(1) 電子發票列印設備 『電子發票列印設備』值參考
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_cloud_type integer(1) 電子發票開立類型-雲端發票類型 『雲端發票類型』值參考
invoice_mobile_code string(20) 當invoice_cloud_type為2時紀錄的手機條碼
invoice_tax_id string(8) 當invoice_cloud_type為2時紀錄的統一編號
invoice_natural_person string(20) 當invoice_cloud_type為3時紀錄的自然人憑證條碼
invoice_love_code string(20) 當invoice_input_type為2時紀錄的愛心碼
invoice_b2b_title string(50) 當invoice_input_type為3時紀錄的發票抬頭
invoice_b2b_id string(8) 當invoice_input_type為3時紀錄的統一編號
invoice_b2b_post_zone string(10) 當invoice_input_type為3時紀錄的郵遞區號
invoice_b2b_address string(200) 當invoice_input_type為3時紀錄的發票地址

直接交易查詢

<?php
/**
 * 經銷商串接-直接交易查詢
 */
final class AgentQueryDirect
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 特約商店金鑰或認證碼
     * @var string
     */
    public $storeKey = "5p8LnrEiuwUn8Zn5yH31s0mg3Jjq5elB";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['order_id']  = '53654';
        $rawData['user_id']   = 'phper';
        $rawData['cost']      = '10';

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/querydirect'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);<
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentQueryDirect = new AgentQueryDirect();
$AgentQueryDirect->run();
?>
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-直接交易查詢
    /// </summary>
    public class AgentQueryDirect {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";
        /// <summary>

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentQueryDirect simulator = new AgentQueryDirect();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {
            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.order_id = "2020020210003";
            rawData.user_id = "phper";
            rawData.cost = "10";
            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/querydirect";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }


    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-直接交易查詢
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentQueryDirect {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 特約商店金鑰或認證碼
     */
    String storeKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentQueryDirect simulator = new AgentQueryDirect();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("order_id", "2020020210003");
        rawData.put("user_id", "phper");
        rawData.put("cost", "10");
        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/querydirect");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-直接交易查詢
 */
function AgentQueryDirect() {
    // 經銷商商務代號
    this.agentUid = "518169081001";
    // 特約商店金鑰或認證碼
    this.agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    // 特約商店商務代號
    this.storeUid = "289151880002";
    // 串接交易位置
    this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentQueryDirect.prototype.getRawData = function () {
    return {
        store_uid: this.storeUid,
        order_id: "2020020210003",
        user_id: "phper",
        cost: "10"
    };
};
/**
 * 取得服務位置
 */
AgentQueryDirect.prototype.getService = function () {
    return {
        service_name: "api",
        cmd: "api/querydirect"
    };
};
/**
 * AES 256 加密
 */
AgentQueryDirect.prototype.encrypt = function (fields, key) {
    let eData = JSON.stringify(fields);
    const blockSize = 16;
    const iv = crypto.randomBytes(blockSize);
    const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
    let tmpCipher = encryptor.update(Buffer.from(eData));
    let finalCipher = encryptor.final();
    const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
    let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
    return data;
};
/**
 * 資料 POST 到主機
 */
AgentQueryDirect.prototype.post = function (postData) {
    return new Promise((res, rej) => {
        let options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            rejectUnauthorized: false
        };

        let send_process = httpRequest.request(this.url, options, (api_res) => {
            let res_data = "";
            api_res.on('data', (tmp_data) => {
                res_data += tmp_data;
            });
            api_res.on('end', () => {
                res(res_data);
            });
        });

        send_process.write(JSON.stringify(postData));
        send_process.end();
    });
};
/**
 * 取得送出欄位資料
 */
AgentQueryDirect.prototype.getPostData = function () {
    return {
        "agent_uid": this.agentUid,
        "service": this.encrypt(this.getService(), this.agentKey),
        "encry_data": this.encrypt(this.getRawData(), this.agentKey)
    };
};
/**
 * 執行
 */
AgentQueryDirect.prototype.run = async function () {
    json = await this.post(this.getPostData())
    console.log(json);
};

AgentQueryDirect = new AgentQueryDirect();
AgentQueryDirect.run();
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-直接交易查詢
"""
class AgentQueryDirect:
    # 經銷商商務代號
    agentUid = "518169081001"
    # 經銷商店金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS"
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
                  'agent_uid': self.agentUid,
                  'order_id': "2020020210003",
                  'user_id': "phper",
                  'cost': "10"
              }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/querydirect'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentQueryDirect = AgentQueryDirect()
AgentQueryDirect.run()

回傳 JSON 結構如下:

{
    "code": "B200",
    "msg": "執行成功",
    "rows": [{
        "key": "9d2aefb66584290fe1f56f626ea71680",
        "prc": "300",
        "cardno": "543045******1219",
        "acode": "",
        "card_type": "1",
        "issuing_bank": "國泰世華",
        "issuing_bank_uid": "013",
        "is_agent_charge": 0,
        "transaction_mode": 1,
        "supplier_name": "聯合信用卡處理中心",
        "supplier_code": "B6",
        "order_id": "1234567890",
        "user_id": "phper",
        "uid": 30232,
        "cost": 10,
        "currency": "TWD",
        "actual_cost": 0,
        "actual_currency": "TWD",
        "love_cost": 0,
        "retmsg": "交易失敗",
        "pay_mode_uid": 1,
        "pfn": "CREDITCARD",
        "trans_type": 1,
        "redeem": "",
        "installment": "",
        "finishtime": "",
        "store_group_id": "",
        "nois": "",
        "payment_name": "",
        "bank_id": "",
        "expired_date": "",
        "appropriation_date": "",
        "result_type": 4,
        "result_content_type": "CREDITCARD",
        "result_content": "{}",
        "invoice_state": 0,
        "invoice_date": "",
        "invoice_wordtrack": "",
        "invoice_number": "",
        "invoice_rand_code": "",
        "invoice_seller_ban": "",
        "invoice_buyer_ban": "",
        "invoice_left_qrcode": "",
        "invoice_middle_barcode": "",
        "invoice_right_qrcode": "",
        "invoice_title_type": 1,
        "invoice_title": "",
        "invoice_amount": "0",
        "invoice_sales_amount": "0",
        "invoice_tax_amount": "0",
        "invoice_order_detail": "[]",
        "invoice_ratetype": 1,
        "invoice_input_type": null,
        "invoice_allowance": [],
        "echo_0": "",
        "echo_1": "",
        "echo_2": "",
        "echo_3": "",
        "echo_4": ""
    }]
}

發動交易後,如果遲遲未接收回報,可透過此方法查詢訂單交易。

經銷商直接交易查詢參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/querydirect"}
JSON格式,AES256加密資料
encry_data text 『直接交易查詢』欄位參考
JSON格式,AES256加密資料

『直接交易查詢』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店編號 必填
order_id string(50) 訂單編號 必填
cost string(19) 訂單總金額 必填
user_id string(50) 消費者帳號

回傳資料

欄位 說明 型態 補充說明
code 執行結果 string 參考交易回傳碼
msg 執行結果訊息 string
rows 查詢資料清單 array 交易成功可能含多筆退款或取消以及發票等相關資訊
每筆『交易查詢』欄位參考

特約商店可用支付工具查詢

可查詢目前特約商店所支援的支付工具有哪些,需注意當支付工具有設定不到一定的金額不能使用時,則cost必須要達到該金額以上,否則無法查詢到

<?php
/**
 * 經銷商串接-查詢特約商店支援之支付方式
 */
final class AgentSupportPayMode
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "A1234567891002";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "nq8KL8qNNCW12A3TBfAp4lU0y3PED8IQ";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['cost'] = "1000";
        $rawData['currency'] = "TWD";

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/paymentsupportpaymode'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentSupportPayMode = new AgentSupportPayMode();
$AgentSupportPayMode->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-查詢特約商店支援之支付方式
    /// </summary>
    public class AgentSupportPayMode {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "A1234567891002";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "nq8KL8qNNCW12A3TBfAp4lU0y3PED8IQ";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentSupportPayMode simulator = new AgentSupportPayMode();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.cost = "1000";
            rawData.currency = "TWD";

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/paymentsupportpaymode";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }
    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}


import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-查詢特約商店支援之支付方式
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentSupportPayMode {
    /**
     * 經銷商商務代號
     */
    String agentUid = "A1234567891002";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "nq8KL8qNNCW12A3TBfAp4lU0y3PED8IQ";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentSupportPayMode simulator = new AgentSupportPayMode();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("cost", "1000");
        rawData.put("currency", "TWD");

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/paymentsupportpaymode");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}


const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-查詢特約商店支援之支付方式
 */
function AgentSupportPayMode() {
  // 經銷商商務代號
  this.agentUid = "A1234567891002";
  // 經銷商金鑰或認證碼
  this.agentKey = "nq8KL8qNNCW12A3TBfAp4lU0y3PED8IQ";
  // 特約商店商務代號
  this.storeUid = "289151880002";
  // 串接交易位置
  this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentSupportPayMode.prototype.getRawData = function () {
  return {
    store_uid: this.storeUid,
    cost: "1000",
    currency: "TWD"
  };
};
/**
 * 取得服務位置
 */
AgentSupportPayMode.prototype.getService = function () {
  return {
    service_name: "api",
    cmd: "api/paymentsupportpaymode"
  };
};
/**
 * AES 256 加密
 */
AgentSupportPayMode.prototype.encrypt = function (fields, key) {
  let eData = JSON.stringify(fields);
  const blockSize = 16;
  const iv = crypto.randomBytes(blockSize);
  const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
  let tmpCipher = encryptor.update(Buffer.from(eData));
  let finalCipher = encryptor.final();
  const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
  let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
  return data;
};
/**
 * 資料 POST 到主機
 */
AgentSupportPayMode.prototype.post = function (postData) {
  return new Promise((res, rej) => {
    let options = {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      rejectUnauthorized: false
    };

    let send_process = httpRequest.request(this.url, options, (api_res) => {
      let res_data = "";
      api_res.on('data', (tmp_data) => {
        res_data += tmp_data;
      });
      api_res.on('end', () => {
        res(res_data);
      });
    });

    send_process.write(JSON.stringify(postData));
    send_process.end();
  });
};
/**
 * 取得送出欄位資料
 */
AgentSupportPayMode.prototype.getPostData = function () {
  return {
    "agent_uid": this.agentUid,
    "service": this.encrypt(this.getService(), this.agentKey),
    "encry_data": this.encrypt(this.getRawData(), this.agentKey)
  };
};
/**
 * 執行
 */
AgentSupportPayMode.prototype.run = async function () {
  json = await this.post(this.getPostData())
  console.log(json);
};

AgentSupportPayMode = new AgentSupportPayMode();
AgentSupportPayMode.run();

import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-查詢特約商店支援之支付方式
"""
class AgentSupportPayMode:
    # 經銷商商務代號
    agentUid = "A1234567891002";
    # 經銷商金鑰或認證碼
    agentKey = b"nq8KL8qNNCW12A3TBfAp4lU0y3PED8IQ";
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'cost': "1000",
            'currency': "TWD"
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/paymentsupportpaymode'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentSupportPayMode = AgentSupportPayMode()
AgentSupportPayMode.run()

回傳 JSON 結構如下:

{
  "code": "B200",
  "msg": "執行成功",
  "content": [
    "CREDITCARD",
    "CSTORECODE",
    "WEBATM",
    "E_COLLECTION",
    "ABROAD",
    "MATM",
    "WECHAT",
    "WECHATOFF",
    "LINEPAYON",
    "LINEPAYOFF",
    "APPLEPAY",
    "GOOGLEPAY",
    "CARDLESS",
    "PION",
    "PIOFF",
    "JKOON",
    "JKOOFF",
    "CASH",
    "EASYWALLETON",
    "EASYWALLETOFF",
    "BARCODE"
  ]
}

特約商店『可用支付工具查詢』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/paymentsupportpaymode"}
JSON格式,AES256加密資料
encry_data text 『可用支付工具查詢』欄位參考
JSON格式,AES256加密資料

『可用支付工具查詢』欄位

參數名稱 型態 說明 必須
store_uid string(16) 特約商店商務代號 必要
cost string 交易金額 必要,最小值須為1
cost string 預設交易幣別(預設為TWD新台幣) 『幣別類型』值參考

『可用支付工具查詢』回傳欄位

參數名稱 型態 說明 必須
code string 交易回傳碼(B200或B500或100)
msg string(500) 回傳訊息
content string 支付方式清單(狀態B200才有)

交易退款

<?php
/**
 * 經銷商串接-交易退款
 */
final class AgentRefund
{
    /**
     * 經銷商商務代號
     * @var string
     */
    public $agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     * @var string
     */
    public $agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號(代特約商店發動)
     * @var string
     */
    public $storeUid = "289151880002";
    /**
     * 串接交易位置
     * @var string
     */
    public $url = "https://pay.usecase.cc/api/agent";
    /**
     * 取得串接欄位資料
     * @return array
     */
    public function getRawData()
    {
        $rawData = array();
        $rawData['store_uid'] = $this->storeUid;
        $rawData['uid'] = "88833";
        $rawData['key'] = "1c943777706d68f757afdb9034213001";
        $rawData['cost'] = 100;
        $rawData['invoice_state'] = 6;
        $rawData['items'] = [
                                [
                                 'id' => '1',
                                 'name' => '倚天劍模型',
                                 'cost' => 100,
                                 'amount' => 1,
                                 'total' => 100
                                ]
                            ];

        return $rawData;
    }
    /**
     * 取得服務位置
     * @return array
     */
    public function getService()
    {
        return array(
            'service_name' => 'api',
            'cmd' => 'api/refund'
        );
    }
    /**
     * AES 256 加密
     * @param array $fields
     * @param string $key
     * @return string
     */
    public function encrypt($fields, $key)
    {
        $data = json_encode($fields);
        $size = openssl_cipher_iv_length('AES-256-CBC');
        $iv   = openssl_random_pseudo_bytes($size);
        $data = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
        $data = base64_encode($iv . $data);
        return $data;
    }
    /**
     * 資料 POST 到主機
     * @param array $postData
     * @return mixed
     */
    public function post($postData = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
    /**
     * 取得送出欄位資料
     * @return array
     */
    public function getPostData ()
    {
        $postData = array();
        $postData['agent_uid'] = $this->agentUid;
        $postData['service'] = $this->encrypt($this->getService(), $this->agentKey);
        $postData['encry_data'] = $this->encrypt($this->getRawData(), $this->agentKey);
        return $postData;
    }
    /**
     * 執行
     */
    public function run()
    {
        $json = $this->post($this->getPostData());
        echo $json;
    }
}

$AgentRefund = new AgentRefund();
$AgentRefund->run();
?>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Dynamic;
/// <summary>
/// 建議使用.net framework4.5以上版本
/// 1.請透過NuGet安裝Newtonsoft.Json,若.net framework小於4.5請安裝Newtonsoft.Json 7.0以下版本
/// 2.若貴司.net framework小於4 可能無法使用dynamic,若是自行組陣列
/// 3.若貴司.net framework小於3.5 可能無法使用AES類別,若是參閱微軟網站使用較舊方式進行加密
/// 4.若貴司.net framework小於3.5 可能沒有Linq可使用,故data只能組字串,Newtonsoft.Json也可能無法使用
/// </summary>
namespace MyPay {
    /// <summary>
    /// 經銷商串接-交易退款
    /// </summary>
    public class AgentRefund {
        /// <summary>
        /// 經銷商商務代號
        /// </summary>
        public string agentUid = "518169081001";
        /// <summary>
        /// 經銷商金鑰或認證碼
        /// </summary>
        public string agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
        /// <summary>
        /// 特約商店商務代號
        /// </summary>
        public string storeUid = "289151880002";

        /// <summary>
        /// 串接交易位置
        /// </summary>
        public string url = "https://pay.usecase.cc/api/agent";
        /// <summary>
        /// 執行
        /// </summary>
        static void Main() {
            AgentRefund simulator = new AgentRefund();
            //僅限走https的Tls 1.2以上版本
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            //發送至遠端
            var result = simulator.Post(simulator.GetPostData());

            System.Console.WriteLine(result);
        }
        /// <summary>
        /// 取得串接欄位資料
        /// </summary>
        private dynamic GetRawData() {

            ArrayList items = new ArrayList();

            dynamic item = new ExpandoObject();
            item.id = "1";
            item.name = "倚天劍模型";
            item.cost = 100;
            item.amount = 1;
            item.total = 100;
            items.Add(item);


            dynamic rawData = new ExpandoObject();
            rawData.store_uid = this.storeUid;
            rawData.uid =  "88833";
            rawData.key =  "1c943777706d68f757afdb9034213001";
            rawData.cost =  100;
            rawData.invoice_state =  6;
            rawData.items = items;

            return rawData;
        }
        /// <summary>
        /// 取得服務位置
        /// </summary>
        private ServiceRequest GetService() {
            ServiceRequest rawData = new ServiceRequest();
            rawData.service_name = "api";
            rawData.cmd = "api/refund";
            return rawData;
        }
        /// <summary>
        /// 取得送出欄位資料
        /// </summary>
        private NameValueCollection GetPostData() {
            string data_json = JsonConvert.SerializeObject(GetRawData(), Formatting.None);
            string svr_json = JsonConvert.SerializeObject(GetService(), Formatting.None);; //依API種類調整

            //產生AES向量
            var IV = GetBytesIV();

            //進行加密
            var data_encode = Encrypt(data_json, this.agentKey, IV);
            var svr_encode = Encrypt(svr_json, this.agentKey, IV);

            //請注意使用的 Http Post 套件是否會自動加上UrlEncode,本Post範例為原始方式,故須加上UrlEncode
            //若自行使用的套件會自動補上UrlEncode,則請忽略下面的UrlEncode,避免做了兩次UrlEncode
            string data_toUrlEncode = HttpUtility.UrlEncode(data_encode);
            string svr_toUrlEncode = HttpUtility.UrlEncode(svr_encode);

            NameValueCollection postData = new NameValueCollection();
            postData["agent_uid"] = this.agentUid;
            postData["service"] = svr_toUrlEncode;
            postData["encry_data"] = data_toUrlEncode;
            return postData;
        }
        /// <summary>
        /// AES 256 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="byteIV"></param>
        /// <returns></returns>
        private string Encrypt(string data, string key, byte[] byteIV) {
            var byteKey = System.Text.Encoding.UTF8.GetBytes(key);
            var enBytes = AES_Encrypt(data, byteKey, byteIV);
            return Convert.ToBase64String(BytesAdd(byteIV, enBytes));
        }
        /// <summary>
        /// AES 256 加密處理
        /// </summary>
        /// <param name="original"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <returns></returns>
        private byte[] AES_Encrypt(string original, byte[] key, byte[] iv) {
            try {
                var data = Encoding.UTF8.GetBytes(original);

                var cipher = Aes.Create().CreateEncryptor(key, iv);

                var de = cipher.TransformFinalBlock(data, 0, data.Length);
                return de;
            } catch {
                return null;
            }
        }
        /// <summary>
        /// 轉換Bytes
        /// </summary>
        /// <param name="a"></param>
        /// <param name="arryB"></param>
        /// <returns></returns>
        private byte[] BytesAdd(byte[] a, params byte[][] arryB) {
            List < byte > c = new List < byte > ();
            c.AddRange(a);
            arryB.ToList().ForEach(b => {
                c.AddRange(b);
            });
            return c.ToArray();
        }
        /// <summary>
        /// 產生AES的IV
        /// </summary>
        /// <returns></returns>
        private static byte[] GetBytesIV() {
            var aes = System.Security.Cryptography.AesCryptoServiceProvider.Create();
            aes.KeySize = 256;
            aes.GenerateIV();
            return aes.IV;
        }
        /// <summary>
        /// 資料 POST 到主機
        /// </summary>
        /// <param name="pars"></param>
        /// <returns></returns>
        private string Post(NameValueCollection pars) {
            string result = string.Empty;
            string param = string.Empty;
            if (pars.Count > 0) {
                pars.AllKeys.ToList().ForEach(key => {
                    param += key + "=" + pars[key] + "&";
                });
                if (param[param.Length - 1] == '&') {
                    param = param.Remove(param.Length - 1);
                }
            }
            byte[] bs = Encoding.UTF8.GetBytes(param);

            try {
                HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(this.url);
                req.Method = "POST";
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = bs.Length;
                using(Stream reqStream = req.GetRequestStream()) {
                    reqStream.Write(bs, 0, bs.Length);
                }
                using(WebResponse wr = req.GetResponse()) {
                    Encoding myEncoding = Encoding.GetEncoding("UTF-8");
                    using(StreamReader myStreamReader = new StreamReader(wr.GetResponseStream(), myEncoding)) {
                        result = myStreamReader.ReadToEnd();
                    }
                }

                req = null;
            } catch (WebException ex) {
                throw new WebException(ex.Message + "params : " + param, ex, ex.Status, ex.Response);
            }
            return result;
        }
    }
    /// <summary>
    /// 串接服務請求欄位
    /// </summary>
    public class ServiceRequest {
        public string service_name { get; set; }
        public string cmd { get; set; }
    }
}

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URLEncoder;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.spongycastle.crypto.engines.AESEngine;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.SecureRandom;
/**
 * 經銷商串接-交易退款
 * 1. jackson-core 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
 * 2. jackson-databind 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
 * 3. jackson-annotations 下載 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
 * 4. Spongy Castle 下載 https://mvnrepository.com/artifact/com.madgag.spongycastle/core
 */
public class AgentRefund {
    /**
     * 經銷商商務代號
     */
    String agentUid = "518169081001";
    /**
     * 經銷商金鑰或認證碼
     */
    String agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    /**
     * 特約商店商務代號
     */
    String storeUid = "289151880002";
    /**
     * 串接交易位置
     */
    String url = "https://pay.usecase.cc/api/agent";
    /**
     * 執行
     * @param  args
     */
    public static void main(String[] args) {
        AgentRefund simulator = new AgentRefund();
        String json = simulator.post(simulator.getPostData());
        System.out.print(json);
    }

    @SuppressWarnings(value = { "unchecked", "deprecation" })
    /**
     * 取得串接欄位資料
     * @return 串接原始資料
     */
    public Map getRawData() {

        ArrayList items = new ArrayList();

        Map<Object, Object> item = new HashMap<Object, Object>();
        item.put("id", "1");
        item.put("name", "倚天劍模型");
        item.put("cost", 100);
        item.put("amount", 1);
        item.put("total", 100);
        items.add(item);


        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("store_uid", this.storeUid);
        rawData.put("uid", "88833");
        rawData.put("key", "1c943777706d68f757afdb9034213001");
        rawData.put("cost", 100);
        rawData.put("invoice_state", 6);
        rawData.put("items", items);

        return rawData;
    }
    /**
     * 取得服務位置
     * @return 串接服務資料
     */
    public Map getService() {
        Map<Object, Object> rawData = new HashMap<Object, Object>();
        rawData.put("service_name", "api");
        rawData.put("cmd", "api/refund");
        return rawData;
    }
    /**
     * AES 256 加密
     * @param rawData 原始資料
     * @param AesKey AES256金鑰字串
     * @return 轉換成Base64資料
     */
    public String encrypt(Map rawData, String AesKey) {

        try {
            ObjectMapper objMapper = new ObjectMapper();

            byte[] data = objMapper.writeValueAsString(rawData).getBytes(UTF_8);
            byte[] key = AesKey.getBytes(UTF_8);

            // 16 bytes is the IV size for AES256
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                    new CBCBlockCipher(new AESEngine()));
            // Random iv
            SecureRandom rng = new SecureRandom();
            byte[] ivBytes = new byte[16];
            rng.nextBytes(ivBytes);

            cipher.init(true, new ParametersWithIV(new KeyParameter(key),
                    ivBytes));
            byte[] outBuf = new byte[cipher.getOutputSize(data.length)];

            int processed = cipher
                    .processBytes(data, 0, data.length, outBuf, 0);
            processed += cipher.doFinal(outBuf, processed);

            byte[] outBuf2 = new byte[processed + 16]; // Make room for iv
            System.arraycopy(ivBytes, 0, outBuf2, 0, 16); // Add iv
            System.arraycopy(outBuf, 0, outBuf2, 16, processed);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outBuf2);
            return base64;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }
    /**
     * 資料 POST 到主機
     * @param qstr 串接資料
     * @return 服務回傳JSON資訊
     */
    public String post(String qstr) {
        String result = "";
        try {
            // 資料
            byte[] qstr_bytes = qstr.getBytes(StandardCharsets.UTF_8);

            URL iurl = new URL(this.url);
            SSLContext sc = SSLContext.getInstance("TLSv1.2"); // $NON-NLS-1$
            sc.init(null, null, new java.security.SecureRandom());

            HttpsURLConnection con = (HttpsURLConnection) iurl.openConnection();
            con.setSSLSocketFactory(sc.getSocketFactory());
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length",
                    String.valueOf(qstr_bytes.length));
            con.setRequestProperty("Accept-Charset", "UTF-8");

            con.setDoOutput(true);
            con.setDoInput(true);

            con.getOutputStream()
                    .write(qstr.getBytes(Charset.forName("UTF-8")));
            con.getOutputStream().flush();

            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream(), "UTF-8"));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine + "\r\n");
            }

            try {
                result = response.toString();
            } finally {
                in.close();
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return result;
    }
    /**
     * 取得送出欄位資料
     * @return POST完整資料
     */
    public String getPostData() {
        String postData = "";
        try {
            // Base64需要使用UrlEncode做傳輸
            String data_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getRawData(), this.agentKey), "UTF-8");
            String svr_toUrlEncode = URLEncoder.encode(
                    this.encrypt(this.getService(), this.agentKey), "UTF-8");

            postData = "agent_uid=" + this.agentUid + "&service="
                    + svr_toUrlEncode + "&encry_data=" + data_toUrlEncode;
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return postData;
    }
}

const crypto = require('crypto');
const httpRequest = require('https');

/**
 * 經銷商串接-交易退款
 */
function AgentRefund() {
  // 經銷商商務代號
  this.agentUid = "518169081001";
  // 經銷商金鑰或認證碼
  this.agentKey = "0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
  // 特約商店商務代號
  this.storeUid = "289151880002";
  // 串接交易位置
  this.url = "https://pay.usecase.cc/api/agent";
};
/**
 * 取得串接欄位資料
 */
AgentRefund.prototype.getRawData = function () {
  return {
    store_uid: this.storeUid,
    uid: "88833",
    key: "1c943777706d68f757afdb9034213001",
    cost: 100,
    invoice_state: 6,
    items: [
      {
        'id': "1",
        'name': "倚天劍模型",
        'cost': 100,
        'amount': 1,
        'total': 100
      }
    ],

  };
};
/**
 * 取得服務位置
 */
AgentRefund.prototype.getService = function () {
  return {
    service_name: "api",
    cmd: "api/refund"
  };
};
/**
 * AES 256 加密
 */
AgentRefund.prototype.encrypt = function (fields, key) {
  let eData = JSON.stringify(fields);
  const blockSize = 16;
  const iv = crypto.randomBytes(blockSize);
  const encryptor = crypto.createCipheriv('aes-256-cbc', key, iv);
  let tmpCipher = encryptor.update(Buffer.from(eData));
  let finalCipher = encryptor.final();
  const tempData = Buffer.concat([tmpCipher, finalCipher], tmpCipher.length + finalCipher.length);
  let data = Buffer.concat([iv, tempData], iv.length + tempData.length).toString('base64');
  return data;
};
/**
 * 資料 POST 到主機
 */
AgentRefund.prototype.post = function (postData) {
  return new Promise((res, rej) => {
    let options = {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      rejectUnauthorized: false
    };

    let send_process = httpRequest.request(this.url, options, (api_res) => {
      let res_data = "";
      api_res.on('data', (tmp_data) => {
        res_data += tmp_data;
      });
      api_res.on('end', () => {
        res(res_data);
      });
    });

    send_process.write(JSON.stringify(postData));
    send_process.end();
  });
};
/**
 * 取得送出欄位資料
 */
AgentRefund.prototype.getPostData = function () {
  return {
    "agent_uid": this.agentUid,
    "service": this.encrypt(this.getService(), this.agentKey),
    "encry_data": this.encrypt(this.getRawData(), this.agentKey)
  };
};
/**
 * 執行
 */
AgentRefund.prototype.run = async function () {
  json = await this.post(this.getPostData())
  console.log(json);
};

AgentRefund = new AgentRefund();
AgentRefund.run();

# -*- coding: utf-8 -*-
import json
import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util import Padding
from Crypto.Random import get_random_bytes

"""經銷商串接-交易退款
"""
class AgentRefund:
    # 經銷商商務代號
    agentUid = "518169081001";
    # 經銷商金鑰或認證碼
    agentKey = b"0DZP5XgV1dLXXNQqNUFZ7UXvSP6DBalS";
    # 特約商店商務代號
    storeUid = "289151880002"
    # 串接交易位置
    url = "https://pay.usecase.cc/api/agent"

    def getRawData(self):
        """取得串接欄位資料

        Returns:
            {dict}: 欄位資料
        """
        rawData = {
            'store_uid': self.storeUid,
            'uid': "88833",
            'key': "1c943777706d68f757afdb9034213001",
            'cost': 100,
            'invoice_state': 6,
            'items': [
                         {
                          'id': "1",
                          'name': "倚天劍模型",
                          'cost': 100,
                          'amount': 1,
                          'total': 100
                         }
                     ],
        }
        return rawData

    def getService(self):
        """取得服務位置

        Returns:
            {dict}: 服務位置資料
        """
        return {
            'service_name': 'api',
            'cmd': 'api/refund'
        }

    def encrypt(self, fields, key):
        """AES 256 加密

        Args:
            fields {dict}: 欄位資料
            key {bytes}: AES金鑰

        Returns:
            {string}: 加密資料
        """
        data = json.dumps(fields, separators=(',', ':'))
        data = Padding.pad(data.encode('utf-8'), AES.block_size)
        iv = get_random_bytes(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        data = cipher.encrypt(data)
        data = base64.b64encode(iv + data)
        return data

    def post(self, postData):
        """資料 POST 到主機

        Args:
            postData {dict}: 欄位資料

        Returns:
            {string}: JSON資料
        """
        result = requests.post(self.url, postData)
        return result.text

    def getPostData(self):
        """取得送出欄位資料

        Returns:
            {dict}: 欄位資料
        """
        postData = {
            'agent_uid': self.agentUid,
            'service': self.encrypt(self.getService(), self.agentKey),
            'encry_data': self.encrypt(self.getRawData(), self.agentKey)
        }
        return postData

    def run(self):
        """執行
        """
        json = self.post(self.getPostData())
        print(json)

AgentRefund = AgentRefund()
AgentRefund.run()

回傳 JSON 結構如下:

{
  "row_data": {
    "uid": 88833,
    "refund_uid": 88834,
    "key": "1c943777706d68f757afdb9034213001",
    "prc": "230",
    "finishtime": "20210701104600",
    "order_id": "20210701107C23AA66",
    "user_id": "userid",
    "cost": 100,
    "currency": "TWD",
    "actual_cost": 100,
    "actual_currency": "TWD",
    "retmsg": "退款完成",
    "pfn": "CREDITCARD",
    "payment_name": "",
    "nois": "",
    "group_id": "",
    "refund_type": 1,
    "expected_refund_date": "",
    "echo_0": "",
    "echo_1": "",
    "echo_2": "",
    "echo_3": "",
    "echo_4": ""
  },
  "key": "1c943777706d68f757afdb9034213001",
  "uid": "88833",
  "code": "B200",
  "msg": "執行成功"
}

若需要退款時,發動此API提出退款請求。支援即時退款且未超過退款期限內之支付方式皆可使用此方式發動退款。 支援即時退款的支付方式有信用卡、美國運通、LINEPay、Pi錢包、街口支付、微信支付、支付寶、悠遊付、現金、GooglePay、ApplePay。

經銷商『交易退款』參數說明

欄位 型態 說明
agent_uid string(16) 經銷商商務代號
service text {"service_name": "api", "cmd": "api\/refund"}
JSON格式,AES256加密資料
encry_data text 『交易退款』欄位參考
JSON格式,AES256加密資料

『交易退款』欄位

參數名稱 型態 說明 必須
store_uid string 特約商店代碼
key string 交易驗証碼
uid string 訂單編號(UID)
cost string 退款金額(可部分退款)
invoice_state integer 若有開立電子發票,指定電子發票使用作廢或折讓
注意:跨發票月份無法作廢
『電子發票退款時使用作廢或折讓』值參考
items array 退款項目
若使用電子發票,此欄位必填
退款項目之項目名稱必須和交易時之產品項目名稱相同
退款項目之總金額必須與退款金額一致
每筆『商品項目』欄位參考

『交易退款』回傳欄位

參數名稱 型態 說明 必須
key string 特約商店驗證碼 (store_token)
uid string 訂單編號(UID)
code string 處理狀態 B200 或 B500
msg string 回傳訊息
row_data object 退款資訊(即時退款才有此資訊) 『退款完成回傳資訊』欄位參考

其他關聯欄位說明

關聯欄位

『商品項目』欄位

參數名稱 型態 說明 必須
id string(5) 商品編號 必填
name string(50) 商品名稱 必填
cost string(9) 商品單價 必填
amount string(5) 商品數量 必填
total string(9) 商品小計 必填
image_url string(255) 商品圖片連結(僅LINEPay線上使用)

『虛擬帳號回傳欄位』欄位

參數名稱 型態 說明 必須
PinCode string 虛擬帳號
LimitDate string 繳費有效期限,格式YYYYMMDDHHmmss
BankCode string 銀行代碼

『ibon』欄位

參數名稱 型態 說明 必須
PinCode string 超商代碼(可用qrcode被掃)
LimitDate string 超商代碼繳費有效期限,格式YYYYMMDDHHmmss
BarCode1 string 三段條碼繳費條碼1(格式:Code-39 barcode)
BarCode2 string 三段條碼繳費條碼2(格式:Code-39 barcode)
BarCode3 string 三段條碼繳費條碼3(格式:Code-39 barcode)
BarcodeEndDate string 三段條碼繳費期限,格式YYYYMMDDHHmmss

『FamiPort』欄位

參數名稱 型態 說明 必須
PinCode string 繳費代碼(可憑此代碼至設備列印繳費單)
LimitDate string 繳費有效期限,格式YYYYMMDDHHmmss
BarCode1 string 三段條碼繳費條碼1(格式:Code-39 barcode)
BarCode2 string 三段條碼繳費條碼2(格式:Code-39 barcode)
BarCode3 string 三段條碼繳費條碼3(格式:Code-39 barcode)
BarcodeEndDate string 三段條碼繳費期限,格式YYYYMMDDHHmmss

『Hi Life』欄位

參數名稱 型態 說明 必須
PinCode string 代碼(不可用來繳費)
BarCode1 string 繳費條碼1(格式:Code-39 barcode)
BarCode2 string 繳費條碼2(格式:Code-39 barcode)
BarCode3 string 繳費條碼3(格式:Code-39 barcode)
LimitDate string 繳費有效期限,格式YYYYMMDDHHmmss

『超商條碼繳費』欄位

參數名稱 型態 說明 必須
BarCode1 string 繳費條碼1(格式:Code-39 barcode)
BarCode2 string 繳費條碼2(格式:Code-39 barcode)
BarCode3 string 繳費條碼3(格式:Code-39 barcode)
LimitDate string 繳費有效期限,格式YYYYMMDDHHmmss

『交易查詢』欄位

參數名稱 型態 說明 必須
uid string(50) Payment Hub之交易流水號
key string(50) 交易驗証碼
prc string 交易回傳碼
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
cardno string(50) 銀行端口回傳碼
acode string(10) 授權碼
card_type string 信用卡卡別 『信用卡別類型』值參考
issuing_bank string(50) 發卡行
issuing_bank_uid string(50) 發卡銀行代碼
is_agent_charge int(1) 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer(1) 交易服務類型 『交易服務類型』值參考
supplier_name string(50) 交易之金融服務商
supplier_code string(50) 交易之金融服務商代碼 『金流供應商代碼』值參考
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
price string 請求交易點數/金額
actual_price string 實際交易點數/金額
recharge_code string 交易產品代碼
love_cost string 愛心捐款金額
retmsg string(500) 回傳訊息
pfn string(20) 付費方法
trans_type string 付款種類 『交易類型定義』值參考
redeem string 紅利資訊 JSON 格式 『紅利資訊』值參考
installment string 信用卡分期資訊 JSON 格式 『分期資訊』值參考
payment_name string 定期定額式/定期分期式扣款名稱
nois string 定期定額式/定期分期式扣繳期數
group_id string 1.定期定額式扣款編號
2.定期分期式扣款編號
bank_id string 銀行代碼 虛擬帳號資訊
expired_date string 有效日期(YYYYMMDDHHmmss) 虛擬帳號、超商代碼、無卡分期資訊
appropriation_date string 預計撥款日期(YYYYMMDD)
result_type integer 虛擬帳號、超商代碼 資料格式類型 『閘道內容回傳格式類型』值參考
result_content_type string 資料內容所屬支付名稱 『資料內容所屬支付名稱』值參考
result_content string 虛擬帳號、超商代碼 資料內容 『虛擬帳號回傳欄位』值參考
『ibon』值參考
『FamiPort』值參考
『Hi Life』值參考
refund_order array 退款訂單資訊(多筆格式) 每筆『交易查詢-退款資訊』欄位參考
cancel_order array 取消訂單資訊(多筆格式) 每筆『交易查詢-取消資訊』欄位參考
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_date string 發票開立日期(YYYYMMDD)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title integer 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_allowance array 電子發票折讓資訊 每筆『電子發票折讓資訊』欄位參考
items array 訂單商品項目 每筆『商品項目』欄位參考
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5

『商品項目』欄位

參數名稱 型態 說明 必須
id string 商品編號
name string 商品名稱
cost string 商品單價
amount string 商品數量
total string 商品小計

『紅利資訊』欄位

參數名稱 型態 說明 必須
type string 紅利類型 『紅利資訊類型』值參考
used string 紅利折抵點數
amount string 自付金額

『分期資訊』欄位

參數名稱 型態 說明 必須
period_number integer 分期期數
total integer 應付總金額
first integer 第一期應付金額
every integer 第二期起每期應付金額

『交易查詢-退款資訊』欄位

參數名稱 型態 說明 必須
uid string(50) Payment Hub之交易流水號
prc string 交易回傳碼
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
retmsg string(500) 回傳訊息
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
appropriation_date string 預計撥款日期(YYYYMMDD)
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_date string 發票開立日期(YYYYMMDD)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string 電子發票列印標題內容
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_allowance array 電子發票折讓資訊 每筆『電子發票折讓資訊』欄位參考

『交易查詢-取消資訊』欄位

參數名稱 型態 說明 必須
uid string(50) Payment Hub之交易流水號
prc string 交易回傳碼
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
retmsg string(500) 回傳訊息
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)

『電子發票折讓資訊』欄位

參數名稱 型態 說明 必須
uid string 發生之退款交易流水號(UID)
amount integer 電子發票折讓金額
order_detail string 電子發票折讓明細(JSON格式) 『商品細項』值參考

『退款完成回傳資訊』欄位

參數名稱 型態 說明 必須
uid string 原MYPAYLINK 之交易流水號
refund_uid string 退款之交易流水號(若多次退款,每次皆會不同)
key string 交易驗証碼
prc string 主要交易回傳碼(retcode)
finishtime string 退款處理完成時間(YYYYMMDDHHmmss)
order_id string 貴特店系統的訂單編號
user_id string 消費者帳號
cost string 申請之退款金額
currency string 申請之退款幣別
actual_cost string 實際退款金額
actual_currency string 實際退款幣別
retmsg string 回傳訊息
pfn string 付費方法
payment_name string 定期定額式/定期分期式扣款名稱
nois string 定期定額式/定期分期式扣繳期數
group_id string 1.定期定額式扣款編號
2.定期分期式扣款編號
refund_type string 退款類型(1.直接線上退款 2.手動退款(信用卡類) 3.手動退款(現金類)
expected_refund_date string 現金退款預計退款日(YYYYMMDD)
echo_0 string 自訂回傳參數 1
echo_1 string 自訂回傳參數 2
echo_2 string 自訂回傳參數 3
echo_3 string 自訂回傳參數 4
echo_4 string 自訂回傳參數 5

『商品細項』欄位

參數名稱 型態 說明 必須
Description string(50) 商品名稱
Quantity string(10) 數量
UnitPrice string(19) 單價
Amount string(19) 總金額

『後付款送貨資訊』欄位

參數名稱 型態 說明 必須
shipment_type integer 配送方式 『後付款送貨資訊』值參考
company_name string 寄送地公司名稱
department_name string 寄送地部門名稱
name string 收貨姓名 必填
cvs integer 超商類型(超商店到店必填) 『後付款超商取貨』值參考
cvs_store string 超商店號代碼(超商店到店必填)
cvs_store_name string 超商店號名稱(超商店到店必填)
zip_code string 收貨郵遞區號(純宅配必填)
ship_address string 收貨地址(超商店到店為超商店址) 必填
tel string 收貨電話(超商店到店為超商電話) 必填

『後付款交易回傳欄位』欄位

參數名稱 型態 說明 必須
OrderTotalCost string 交易金額
TradeNo string 後付款交易單號
TradeDate string 交易發動時間,格式YYYYMMDDHHmmss

『後付款請款交易回傳欄位』欄位

參數名稱 型態 說明 必須
OrderTotalCost string 出貨交易金額
TradeNo string 後付款交易單號
TradeDate string 出貨交易發動時間,格式YYYYMMDDHHmmss

『後付款出貨查詢-退款資訊』欄位

參數名稱 型態 說明 必須
uid string 退款訂單編號(UID)
code string 交易狀態碼
msg string 交易狀態訊息
cost string(19) 總交易金額
currency string(10) 原交易幣別
actual_cost string(19) 實際交易金額
actual_currency string(10) 實際交易幣別
finishtime string(14) 交易完成時間(YYYYMMDDHHmmss)
invoice_state integer(2) 發票開立狀態 『電子發票開立狀態類型』值參考
invoice_date string 發票開立日期(YYYYMMDD)
invoice_wordtrack string(2) 發票字軌
invoice_number string(8) 發票號碼
invoice_rand_code string(4) 電子發票隨機碼
invoice_seller_ban string(8) 賣方統一編號
invoice_buyer_ban string(8) 買方統一編號
invoice_left_qrcode string(500) 電子發票左邊QrCode內容
invoice_middle_barcode string(50) 電子發票中間Barcode內容(格式Code-39)
invoice_right_qrcode string(1000) 電子發票右邊QrCode內容
invoice_title_type integer(1) 電子發票列印標題格式 『電子發票紙本列印標題類型』值參考
invoice_title string 電子發票列印標題內容
invoice_amount string(19) 電子發票銷售總額
invoice_sales_amount string(19) 電子發票銷售額
invoice_tax_amount string(19) 電子發票稅額
invoice_order_detail string(1000) 電子發票全部產品明細(JSON格式) 『商品細項』值參考
invoice_ratetype integer(1) 電子發票稅率別 『電子發票稅率別』值參考
invoice_input_type integer(1) 電子發票開立類型 『電子發票開立類型』值參考
invoice_allowance array 電子發票折讓資訊 每筆『電子發票折讓資訊』欄位參考

『電票交易回傳欄位』欄位

參數名稱 型態 說明 必須
OrderTotalCost string 交易金額
TradeDate string 交易時間,格式YYYYMMDDHHmmss
Balance string 扣款後餘額
BeforeBalance string 扣款前餘額
AutoTopUpAmount string 自動加值金額
CardId string 電子票證卡號

『電票交易退款完成資訊』欄位

參數名稱 型態 說明 必須
uid string 訂單編號(UID)
refund_uid string 退款之交易流水號(若多次退款,每次皆會不同)
key string(50) 交易驗証碼
code string 交易回傳碼
msg string(500) 回傳訊息
finishtime string 退款處理完成時間(YYYYMMDDHHmmss)
order_id string(50) 貴特店系統的訂單編號
user_id string(50) 消費者帳號
cost string 申請之退款金額
currency string 申請之退款幣別
actual_cost string 實際退款金額
actual_currency string 實際退款幣別
pfn string(20) 付費方法
echo_0 string(255) 自訂回傳參數 1
echo_1 string(255) 自訂回傳參數 2
echo_2 string(255) 自訂回傳參數 3
echo_3 string(255) 自訂回傳參數 4
echo_4 string(255) 自訂回傳參數 5

『全支付線下資料』欄位

參數名稱 型態 說明 必須
pxCode string 全支付qrcode二維條碼資訊 必填
posId string POS 機號或設備機號 必填
posTradeTime string POS 端交易日期時間
remark string 註記

『全支付線下交易回傳欄位』欄位

參數名稱 型態 說明 必須
PosID string POS 機號或設備機號
PosTradeTime string POS 端交易日期時間,格式:YYYYMMDDHHmmss
Remark string 交易註記說明文字
TradeNo string 金流服務商訂單編號
OrderTotalCost string 交易金額
TradeDate string 金流服務商交易時間,格式YYYYMMDDHHmmss
DebitAmount string 付款方式扣款金額(折抵後金額)
InvoiceVehicle string 發票載具
(消費者綁定全支付時設定之發票載具)
MerMemToken string 第三方合作廠商會員識別資訊
Pan string 遮碼卡號
IsControversy string 是否為爭議款 0.不是 1.是

『Line Pay線上交易回傳欄位』欄位

參數名稱 型態 說明 必須
Web string line pay 網頁支付網址
App string line pay app支付網址
TradeNo string 金流服務商訂單編號

『LINE Pay線下資料』欄位

參數名稱 型態 說明 必須
linepayCode string LinePayqrcode二維條碼資訊 必填

『Line Pay線下交易回傳欄位』欄位

參數名稱 型態 說明 必須
TradeNo string 金流服務商訂單編號
OrderTotalCost string 交易金額
TradeDate string 金流服務商交易時間,格式YYYYMMDDHHmmss
InvoiceVehicle string 發票載具
(消費者綁定LINE Pay時設定之發票載具)
RedeemAmount string 折扣金額
RedeemType string 折扣種類『紅利資訊類型』
OrderRealCost string 實際交易金額
PaymentType string 付款方式
CreditAmt string 持卡人自付金額(信用卡使用)
IsControversy integer 爭議款

『Pi線下資料』欄位

參數名稱 型態 說明 必須
piCode string Pi App qrcode二維條碼資訊 必填

『Pi線上資料回傳欄位』欄位

參數名稱 型態 說明 必須
Web string 導頁網址
App string app連結

『Pi線下交易回傳欄位』欄位

參數名稱 型態 說明 必須
TradeNo string 金流服務商訂單編號
OrderTotalCost string 交易金額
TradeDate string 金流服務商交易時間,格式YYYYMMDDHHmmss
InvoiceVehicle string 發票載具
(消費者綁定Pi時設定之發票載具)

『微信線下資料』欄位

參數名稱 型態 說明 必須
piCode string 微信支付 App qrcode二維條碼資訊 必填

『街口線上交易回傳欄位』欄位

參數名稱 型態 說明 必須
Web string 導頁網址+App連結網址
QRCodeUrl string QRCode圖片

『街口線下資料』欄位

參數名稱 型態 說明 必須
jkoCode string 街口支付 App qrcode二維條碼資訊 必填
posId string POS 機號或設備機號 必填
posTradeTime string POS 端交易日期時間
remark string 註記

『街口線下交易回傳欄位』欄位

參數名稱 型態 說明 必須
PosID string POS 機號或設備機號
PosTradeTime string POS 端交易日期時間,格式:YYYYMMDDHHmmss
Remark string 交易註記說明文字
TradeNo string 金流服務商訂單編號
OrderTotalCost string 交易金額
TradeDate string 金流服務商交易時間,格式YYYYMMDDHHmmss
DebitAmount string 付款方式扣款金額(折抵後金額)
InvoiceVehicle string 發票載具
(消費者綁定Pi時設定之發票載具)
MerMemToken string 第三方合作廠商會員識別資訊
Pan string 遮碼卡號
IsControversy string 是否為爭議款 0.不是 1.是

『Apple Pay線下資料』欄位

參數名稱 型態 說明 必須
paymentData json 由ApplePay產生之資料 必填
paymentMethod json 由ApplePay產生之資料 必填
transactionIdentifier string 由ApplePay產生之資料 必填

*.從ApplePay取得Token就應包含上述欄位,不需要修改內容或自行重組,只需將物件轉為Json String置於data_json即可

*.送出前請注意貴司程式是否有UrlEncode/UrlDecode的行為,若導致paymentToken經過轉換,可能丟失原始Token內容,造成付款失敗。

*.規格參考網址https://developer.apple.com/library/archive/documentation/PassKit/Reference/PaymentTokenJSON/PaymentTokenJSON.html#//apple_ref/doc/uid/TP40014929-CH8

『Google Pay線下資料』欄位

請參閱Google官方文件(Google 官方文件 https://developers.google.com/pay/api/android/guides/tutorial#step_3_create_paymentdatarequest_object),請依程式範例與順序取得JSON資料。

下圖例中的步驟2,gateway值請帶入「mypay」,gatewayMerchantId請帶入貴司申請之「商務代號」。 下圖例中的步驟9,請依紅色文字框取得到JSON資料後,直接放入data_json此欄位即可。

JSON 結構如下:

{
  "apiVersionMinor": 0,
  "apiVersion": 2,
  "paymentMethodData": {
    "description": "Visa •••• 1234",
    "tokenizationData": {
      "type": "PAYMENT_GATEWAY",
      "token": "{\"signature\":\"MEQCICA••••\\u003d\\u003d\",\"protocolVersion\":\"ECv1\",\"signedMessage\":\"{\\\"encryptedMessage\\\":\\\"2oGYBPrbBJIAg••••\\\\u003d\\\\u003d\\\",\\\"ephemeralPublicKey\\\":\\\"BOlRJqnD••••\\\\u003d\\\",\\\"tag\\\":\\\"g0lZC4••••\\\\u003d\\\"}\"}"
    },
    "type": "CARD",
    "info": {
      "cardNetwork": "VISA",
      "cardDetails": "1234"
    }
  }
}

『悠遊付線下資料』欄位

參數名稱 型態 說明 必須
ewCode string 悠遊付二維條碼資訊 必填

『悠遊付線下交易回傳欄位』欄位

參數名稱 型態 說明 必須
Remark string 交易註記說明文字
TradeNo string 金流服務商訂單編號
OrderTotalCost string 交易金額
InvoiceVehicle string 發票載具
(消費者綁定Pi時設定之發票載具)
CitizenDigitalCertificate string 自然人憑證條碼
LoveCode string 愛心碼
EventCode string 活動代碼
PaymentType string 付款方式
DebitAmount string 付款方式扣款金額(折抵後金額)

『自行收款交易回傳欄位』欄位

參數名稱 型態 說明 必須
OrderTotalCost string 交易金額
TradeDate string 金流服務商交易時間,格式YYYYMMDDHHmmss

『錢包被掃交易資料』欄位

參數名稱 型態 說明 必須
qrCode string qrcode 交易碼 必填

『支付寶線下交易回傳欄位』欄位

參數名稱 型態 說明 必須
TradeNo string 金流服務商編號
OrderTotalCost string 交易金額
TradeDate string 金流服務商交易時間,格式YYYYMMDDHHmmss

『支付寶線下資料』欄位

參數名稱 型態 說明 必須
alipayCode string alipay qrcode 必填

值的定義

『付款方式』值內容

型態 說明 備註
CREDITCARD string 信用卡
CSTORECODE string 超商代碼
WEBATM string WEBATM
E_COLLECTION string 虛擬帳號
UNIONPAY string 銀聯卡
ABROAD string 海外信用卡
ALIPAY string 支付寶
WECHAT string 微信支付
LINEPAYON string LINE Pay線上付款
LINEPAYOFF string LINE Pay線下付款
WECHATOFF string 微信支付線下
APPLEPAY string APPLE PAY
GOOGLEPAY string Google Pay
CARDLESS string 無卡分期
PION string Pi 拍錢包線上
PIOFF string Pi 拍錢包線下
AMEX string 美國運通
JKOON string 街口支付線上
JKOOFF string 街口支付線下
ALIPAYOFF string 支付寶線下
EASYWALLETON string 悠遊付線上
EASYWALLETOFF string 悠遊付線下
PXPAYOFF string 全支付線下
AFP string 後付款
OFFLINE string 錢包被掃交易
CREDITCARDALL string 線下信用卡交易
ESVC string 電票交易
EACH string eACH交易
BARCODE string 超商繳費代碼

『回傳付款方式』值內容

型態 說明 備註
CREDITCARD string 信用卡
CSTORECODE string 超商代碼
WEBATM string WEBATM
E_COLLECTION string 虛擬帳號
UNIONPAY string 銀聯卡
ABROAD string 海外信用卡
ALIPAY string 支付寶
WECHAT string 微信支付
LINEPAYON string LINE Pay線上付款
LINEPAYOFF string LINE Pay線下付款
WECHATOFF string 微信支付線下
APPLEPAY string APPLE PAY
GOOGLEPAY string Google Pay
CARDLESS string 無卡分期
PION string Pi 拍錢包線上
PIOFF string Pi 拍錢包線下
AMEX string 美國運通
JKOON string 街口支付線上
JKOOFF string 街口支付線下
ALIPAYOFF string 支付寶線下
EASYWALLETON string 悠遊付線上
EASYWALLETOFF string 悠遊付線下
PXPAYOFF string 全支付線下
AFP string 後付款
EACH string eACH交易
BARCODE string 超商繳費代碼
EASYCARD string 悠遊卡
IPASS string 一卡通
ICASH string iCash

『電票類型』值內容

型態 說明 備註
EASYCARD string 悠遊卡
IPASS string 一卡通
ICASH string iCash

『證號類型』值內容

型態 說明 備註
1 integer 身份證字號(預設)
2 integer 統一證號
3 integer 護照號碼

『幣別類型』值內容

型態 說明 備註
TWD integer 新台幣(預設)
CNY integer 人民幣

『電子發票是否開立狀態』值內容

型態 說明 備註
0 integer 不開立電子發票
1 integer 開立電子發票
2 integer 依系統設定(預設)

『電子發票稅率別』值內容

型態 說明 備註
1 integer 應稅(預設)
2 integer 零稅率
3 integer 免稅

『電子發票開立類型』值內容

型態 說明 備註
0 integer 未使用電子發票開立
1 integer 雲端發票
2 integer 發票捐贈
3 integer 實體發票 重要提示,若選擇此模式,商戶需要自行列印實體發票交付給消費者,系統不會寄送mail通知與中獎後也不會通知給消費者。電子發票列印格式,請參考國稅局頒布標準。

『雲端發票類型』值內容

型態 說明 備註
0 integer 未使用雲端發票類型
2 integer 手機條碼
3 integer 自然人憑證條碼
4 integer 以E-Mail寄送

『含不含簡訊費』值內容

型態 說明 備註
1 integer 含手續費
0 integer 不含手續費(預設)

『含不含手續費類型』值內容

型態 說明 備註
1 integer 含手續費
0 integer 不含手續費(預設)

『交易服務類型』值內容

型態 說明 備註
0 integer 尚未進行閘道交易
1 integer 代收代付
2 integer 特店模式

『金流供應商代碼』值內容

型態 說明 備註
A1 string 裕富數位資融
A2 string 三環亞洲
B0 string 新光銀行
B1 string 永豐銀行
B2 string 合作金庫
B3 string 台北富邦
B4 string 玉山銀行
B5 string 台新銀行
B6 string 聯合信用卡處理中心
B7 string 台中商銀
B8 string 中國信託商業銀行
B9 string 上海商業儲蓄銀行
BA string 第一銀行
BB string 元大商業銀行
BC string 凱基銀行
BD string 國泰世華商業銀行
BE string 華泰商業銀行
BF string 兆豐銀行
BG string 環滙亞太
S0 string 全網行銷股份有限公司(FamiPort)
S1 string 安源資訊股份有限公司(ibon)
S2 string 萊爾富國際股份有限公司(Hi-Life)
T0 string 高鉅科技
T1 string 藍新金流
T2 string 統一客樂得(黑貓Pay)
W0 string 統振
W1 string 遊戲橘子數位
W2 string 台灣連線(LINEPay)
W3 string 博經
W4 string 街口電子支付
W5 string 悠遊卡
W6 string 一卡通票證
W7 string iCash
W8 string 全支付(PXPay plus)
W9 string 拍付國際資訊(Pi錢包)
E0 string MYTIX

『交易類型定義』值內容

型態 說明 備註
1 integer 一般 (預設)
2 integer 分期
3 integer 紅利

『紅利資訊類型』值內容

型態 說明 備註
1 integer 全額
2 integer 部分

『閘道內容回傳格式類型』值內容

型態 說明 備註
0 integer 無法辨識
1 integer 網址
2 integer 超連結本文
3 integer xml
4 integer json
5 integer csv
6 integer 串流

『電子發票開立狀態類型』值內容

型態 說明 備註
0 integer 不處理(預設)
1 integer 等候處理中,
2 integer 發票處理成功
3 integer 發票處理失敗
4 integer 作癈
5 integer 發票號碼設定不正確

『電子發票紙本列印標題類型』值內容

型態 說明 備註
1 integer 文字
2 integer 圖形(圖片網址)

『後付款送貨資訊』值內容

型態 說明 備註
2 integer 純宅配
4 integer 超商店到店

『後付款超商取貨』值內容

型態 說明 備註
1 integer 7-11
2 integer 全家

『貨運商家編號』值內容

型態 說明 備註
0 integer 無法辨識
1 integer 黑貓宅急便
2 integer 台灣宅配通
3 integer 新竹貨運
4 integer 大榮貨運
5 integer 中華郵政
6 integer 便利帶
7 integer 大智通物流
8 integer 日翊文化行銷
9 integer EMS
10 integer 國際e郵包
11 integer 大和國際宅急便
12 integer 佐川國際宅急便
13 integer Dmail/Pmail
14 integer ECMS日本

『資料內容所屬支付名稱』值內容

型態 說明 備註
E_COLLECTION string 虛擬帳號
IBON string iBON
FAMIPORT string FamiPort
LIFEET string LIFE-ET
WEBATM string WEBATM
CREDITCARD string 信用卡
UNIONPAY string 銀聯卡
SVC string 點數卡(GASH ,Imoney)
ABROAD string 海外信用卡
ALIPAY string 支付寶
WECHAT string 微信支付
LINEPAYON string LINE Pay線上付款
LINEPAYOFF string LINE Pay線下付款
WECHATOFF string 微信支付線下
APPLEPAY string APPLE PAY
GOOGLEPAY string Google Pay
EACH string eACH交易
CARDLESS string 無卡分期
PION string Pi 拍錢包線上
PIOFF string Pi 拍錢包線下
AMEX string 美國運通
JKOON string 街口支付線上
JKOOFF string 街口支付線下
ALIPAYOFF string 支付寶線下
EASYWALLETON string 悠遊付線上
EASYWALLETOFF string 悠遊付線下
PXPAYOFF string 全支付線下
AFP string 後付款
BARCODE string 超商條碼繳費

『信用卡別類型』值內容

型態 說明 備註
0 integer 無法辨識或支付方式為非信用卡類
1 integer VISA
2 integer MasterCard
3 integer JCB
4 integer AMEX

『電子發票退款時使用作廢或折讓』值內容

型態 說明 備註
4 integer 作廢或作廢重開 預設
6 integer 折讓

『是否為經銷商代收費模式』值內容

型態 說明 備註
1 integer 是經銷商代收費模式
0 integer 不是經銷商代收費模式

『自行收款付款方式』值內容

型態 說明 備註
CASH string 現金交易
ZINGALAPAY string 銀角零卡
LINEPAY string LINE Pay
JKO string 街口支付
PI string Pi 拍錢包
EASYWALLET string 悠遊付
PXPAY string 全支付
PLUSPAY string 全盈支付
REMITTENCE string 轉帳匯款(無分類)
REMITTENCE_000 string 轉帳匯款(中央銀行)
REMITTENCE_004 string 轉帳匯款(臺灣銀行)
REMITTENCE_005 string 轉帳匯款(土地銀行)
REMITTENCE_006 string 轉帳匯款(合作金庫)
REMITTENCE_007 string 轉帳匯款(第一銀行)
REMITTENCE_008 string 轉帳匯款(華南銀行)
REMITTENCE_009 string 轉帳匯款(彰化銀行)
REMITTENCE_011 string 轉帳匯款(上海銀行)
REMITTENCE_012 string 轉帳匯款(台北富邦)
REMITTENCE_013 string 轉帳匯款(國泰世華)
REMITTENCE_016 string 轉帳匯款(高雄銀行)
REMITTENCE_017 string 轉帳匯款(兆豐銀行)
REMITTENCE_018 string 轉帳匯款(農業金庫)
REMITTENCE_020 string 轉帳匯款(日商瑞穗銀行)
REMITTENCE_021 string 轉帳匯款(花旗銀行)
REMITTENCE_022 string 轉帳匯款(美國銀行)
REMITTENCE_023 string 轉帳匯款(盤谷銀行)
REMITTENCE_025 string 轉帳匯款(首都銀行)
REMITTENCE_029 string 轉帳匯款(新加坡大華銀行)
REMITTENCE_030 string 轉帳匯款(美商道富銀行)
REMITTENCE_037 string 轉帳匯款(法商法國興業銀行台北分行)
REMITTENCE_039 string 轉帳匯款(澳盛銀行)
REMITTENCE_048 string 轉帳匯款(王道銀行)
REMITTENCE_050 string 轉帳匯款(臺灣企銀)
REMITTENCE_052 string 轉帳匯款(渣打銀行)
REMITTENCE_053 string 轉帳匯款(台中銀行)
REMITTENCE_054 string 轉帳匯款(京城銀行)
REMITTENCE_060 string 轉帳匯款(兆豐票券)
REMITTENCE_061 string 轉帳匯款(中華票券)
REMITTENCE_062 string 轉帳匯款(國際票券)
REMITTENCE_066 string 轉帳匯款(萬通票券)
REMITTENCE_072 string 轉帳匯款(德意志銀行)
REMITTENCE_075 string 轉帳匯款(東亞銀行)
REMITTENCE_076 string 轉帳匯款(摩根大通銀行)
REMITTENCE_081 string 轉帳匯款(滙豐銀行)
REMITTENCE_082 string 轉帳匯款(巴黎銀行)
REMITTENCE_085 string 轉帳匯款(新加坡華僑銀行)
REMITTENCE_086 string 轉帳匯款(東方匯理銀行)
REMITTENCE_092 string 轉帳匯款(瑞士銀行)
REMITTENCE_093 string 轉帳匯款(安智銀行)
REMITTENCE_098 string 轉帳匯款(三菱東京日聯銀行)
REMITTENCE_101 string 轉帳匯款(瑞興銀行)
REMITTENCE_102 string 轉帳匯款(華泰銀行)
REMITTENCE_103 string 轉帳匯款(新光銀行)
REMITTENCE_104 string 轉帳匯款(台北五信)
REMITTENCE_108 string 轉帳匯款(陽信銀行)
REMITTENCE_114 string 轉帳匯款(基隆一信)
REMITTENCE_115 string 轉帳匯款(基隆二信)
REMITTENCE_118 string 轉帳匯款(板信銀行)
REMITTENCE_119 string 轉帳匯款(淡水一信)
REMITTENCE_120 string 轉帳匯款(淡水信合社)
REMITTENCE_124 string 轉帳匯款(宜蘭信合社)
REMITTENCE_127 string 轉帳匯款(桃園信合社)
REMITTENCE_130 string 轉帳匯款(新竹一信)
REMITTENCE_132 string 轉帳匯款(新竹三信)
REMITTENCE_146 string 轉帳匯款(台中二信)
REMITTENCE_147 string 轉帳匯款(三信銀行)
REMITTENCE_158 string 轉帳匯款(彰化一信)
REMITTENCE_161 string 轉帳匯款(彰化五信)
REMITTENCE_162 string 轉帳匯款(彰化六信)
REMITTENCE_163 string 轉帳匯款(彰化十信)
REMITTENCE_165 string 轉帳匯款(鹿港信合社)
REMITTENCE_178 string 轉帳匯款(嘉義三信)
REMITTENCE_188 string 轉帳匯款(台南三信)
REMITTENCE_204 string 轉帳匯款(高雄三信)
REMITTENCE_215 string 轉帳匯款(花蓮一信)
REMITTENCE_216 string 轉帳匯款(花蓮二信)
REMITTENCE_222 string 轉帳匯款(澎湖一信)
REMITTENCE_223 string 轉帳匯款(澎湖二信)
REMITTENCE_224 string 轉帳匯款(金門信合社)
REMITTENCE_321 string 轉帳匯款(三井住友銀行)
REMITTENCE_326 string 轉帳匯款(西班牙商西班牙對外銀行臺北分行)
REMITTENCE_329 string 轉帳匯款(印尼人民銀行)
REMITTENCE_330 string 轉帳匯款(韓亞銀行)
REMITTENCE_372 string 轉帳匯款(大慶票券)
REMITTENCE_380 string 轉帳匯款(中國銀行)
REMITTENCE_381 string 轉帳匯款(交通銀行)
REMITTENCE_382 string 轉帳匯款(中國建設銀行)
REMITTENCE_501 string 轉帳匯款(宜蘭縣蘇澳區漁會)
REMITTENCE_502 string 轉帳匯款(宜蘭縣頭城區漁會)
REMITTENCE_503 string 轉帳匯款(基隆漁會)
REMITTENCE_504 string 轉帳匯款(瑞芳/萬里漁會)
REMITTENCE_505 string 轉帳匯款(頭城/蘇澳漁會)
REMITTENCE_506 string 轉帳匯款(桃園漁會)
REMITTENCE_507 string 轉帳匯款(新竹漁會)
REMITTENCE_508 string 轉帳匯款(通苑區漁會)
REMITTENCE_510 string 轉帳匯款(農金資中心)
REMITTENCE_511 string 轉帳匯款(彰化區漁會)
REMITTENCE_512 string 轉帳匯款(雲林區漁會)
REMITTENCE_513 string 轉帳匯款(新北市瑞芳區漁會)
REMITTENCE_514 string 轉帳匯款(萬里區漁會)
REMITTENCE_515 string 轉帳匯款(嘉義區漁會)
REMITTENCE_516 string 轉帳匯款(基隆區漁會)
REMITTENCE_517 string 轉帳匯款(南市區漁會)
REMITTENCE_518 string 轉帳匯款(南縣區漁會)
REMITTENCE_519 string 轉帳匯款(新化區農會)
REMITTENCE_520 string 轉帳匯款(小港區漁會;高雄區漁會)
REMITTENCE_521 string 轉帳匯款(彌陀/永安/興達港/林園區漁會)
REMITTENCE_523 string 轉帳匯款(東港/琉球/林邊區漁會)
REMITTENCE_524 string 轉帳匯款(新港區漁會)
REMITTENCE_525 string 轉帳匯款(澎湖區漁會)
REMITTENCE_526 string 轉帳匯款(南農中心)
REMITTENCE_538 string 轉帳匯款(宜蘭市農會)
REMITTENCE_541 string 轉帳匯款(白河區農會)
REMITTENCE_542 string 轉帳匯款(麻豆區農會)
REMITTENCE_547 string 轉帳匯款(後壁區農會)
REMITTENCE_549 string 轉帳匯款(下營區農會)
REMITTENCE_551 string 轉帳匯款(官田區農會)
REMITTENCE_552 string 轉帳匯款(大內區農會)
REMITTENCE_556 string 轉帳匯款(學甲區農會)
REMITTENCE_557 string 轉帳匯款(新市區農會)
REMITTENCE_558 string 轉帳匯款(安定區農會)
REMITTENCE_559 string 轉帳匯款(山上區農會)
REMITTENCE_561 string 轉帳匯款(左鎮區農會)
REMITTENCE_562 string 轉帳匯款(仁德區農會)
REMITTENCE_564 string 轉帳匯款(關廟區農會)
REMITTENCE_565 string 轉帳匯款(龍崎區農會)
REMITTENCE_567 string 轉帳匯款(南化區農會)
REMITTENCE_568 string 轉帳匯款(七股區農會)
REMITTENCE_570 string 轉帳匯款(南投市農會)
REMITTENCE_573 string 轉帳匯款(埔里鎮農會)
REMITTENCE_574 string 轉帳匯款(竹山鎮農會)
REMITTENCE_575 string 轉帳匯款(中寮鄉農會)
REMITTENCE_577 string 轉帳匯款(魚池鄉農會)
REMITTENCE_578 string 轉帳匯款(水里鄉農會)
REMITTENCE_579 string 轉帳匯款(國姓鄉農會)
REMITTENCE_580 string 轉帳匯款(鹿谷鄉農會)
REMITTENCE_581 string 轉帳匯款(信義鄉農會)
REMITTENCE_582 string 轉帳匯款(仁愛鄉農會)
REMITTENCE_583 string 轉帳匯款(東山區農會)
REMITTENCE_585 string 轉帳匯款(頭城鎮農會)
REMITTENCE_586 string 轉帳匯款(羅東鎮農會)
REMITTENCE_587 string 轉帳匯款(礁溪鄉農會)
REMITTENCE_588 string 轉帳匯款(壯圍鄉農會)
REMITTENCE_589 string 轉帳匯款(員山鄉農會)
REMITTENCE_596 string 轉帳匯款(五結鄉農會)
REMITTENCE_598 string 轉帳匯款(蘇澳地區農會)
REMITTENCE_599 string 轉帳匯款(三星地區農會)
REMITTENCE_600 string 轉帳匯款(農金資訊股份有限公司)
REMITTENCE_602 string 轉帳匯款(中華民國農會中壢辦事處信用部)
REMITTENCE_603 string 轉帳匯款(基隆地區農會)
REMITTENCE_605 string 轉帳匯款(高雄市農會)
REMITTENCE_606 string 轉帳匯款(新北市農會)
REMITTENCE_607 string 轉帳匯款(宜蘭地區農會)
REMITTENCE_608 string 轉帳匯款(桃園地區農會)
REMITTENCE_609 string 轉帳匯款(中華民國農會)
REMITTENCE_610 string 轉帳匯款(新竹地區農會)
REMITTENCE_611 string 轉帳匯款(後龍農會)
REMITTENCE_612 string 轉帳匯款(豐原市農會;神岡鄉農會)
REMITTENCE_613 string 轉帳匯款(名間/集集農會)
REMITTENCE_614 string 轉帳匯款(彰化地區農會)
REMITTENCE_615 string 轉帳匯款(基隆市農會)
REMITTENCE_616 string 轉帳匯款(雲林地區農會)
REMITTENCE_617 string 轉帳匯款(嘉義地區農會)
REMITTENCE_618 string 轉帳匯款(台南地區農會)
REMITTENCE_619 string 轉帳匯款(高雄地區農會)
REMITTENCE_620 string 轉帳匯款(屏東地區農會)
REMITTENCE_621 string 轉帳匯款(花蓮地區農會)
REMITTENCE_622 string 轉帳匯款(台東地區農會)
REMITTENCE_623 string 轉帳匯款(台北市農會)
REMITTENCE_624 string 轉帳匯款(澎湖農會)
REMITTENCE_625 string 轉帳匯款(台中市農會)
REMITTENCE_627 string 轉帳匯款(連江縣農會)
REMITTENCE_628 string 轉帳匯款(鹿港鎮農會)
REMITTENCE_629 string 轉帳匯款(和美鎮農會)
REMITTENCE_631 string 轉帳匯款(溪湖鎮農會)
REMITTENCE_632 string 轉帳匯款(田中鎮農會)
REMITTENCE_633 string 轉帳匯款(北斗鎮農會)
REMITTENCE_635 string 轉帳匯款(線西鄉農會)
REMITTENCE_636 string 轉帳匯款(伸港鄉農會)
REMITTENCE_638 string 轉帳匯款(花壇鄉農會)
REMITTENCE_639 string 轉帳匯款(大村鄉農會)
REMITTENCE_642 string 轉帳匯款(社頭鄉農會)
REMITTENCE_643 string 轉帳匯款(二水鄉農會)
REMITTENCE_646 string 轉帳匯款(大城鄉農會)
REMITTENCE_647 string 轉帳匯款(溪州鄉農會)
REMITTENCE_649 string 轉帳匯款(埔鹽鄉農會)
REMITTENCE_650 string 轉帳匯款(福興鄉農會)
REMITTENCE_651 string 轉帳匯款(彰化市農會)
REMITTENCE_683 string 轉帳匯款(北港鎮農會)
REMITTENCE_685 string 轉帳匯款(土庫鎮農會)
REMITTENCE_693 string 轉帳匯款(東勢鄉農會)
REMITTENCE_696 string 轉帳匯款(水林鄉農會)
REMITTENCE_697 string 轉帳匯款(元長鄉農會)
REMITTENCE_698 string 轉帳匯款(麥寮鄉農會)
REMITTENCE_699 string 轉帳匯款(林內鄉農會)
REMITTENCE_700 string 轉帳匯款(中華郵政)
REMITTENCE_749 string 轉帳匯款(內埔地區農會)
REMITTENCE_762 string 轉帳匯款(大溪區農會)
REMITTENCE_763 string 轉帳匯款(桃園區農會)
REMITTENCE_764 string 轉帳匯款(平鎮區農會)
REMITTENCE_765 string 轉帳匯款(楊梅區農會)
REMITTENCE_766 string 轉帳匯款(大園區農會)
REMITTENCE_767 string 轉帳匯款(蘆竹區農會)
REMITTENCE_768 string 轉帳匯款(龜山區農會)
REMITTENCE_769 string 轉帳匯款(八德區農會)
REMITTENCE_770 string 轉帳匯款(新屋區農會)
REMITTENCE_771 string 轉帳匯款(龍潭區農會)
REMITTENCE_772 string 轉帳匯款(復興區農會)
REMITTENCE_773 string 轉帳匯款(觀音區農會)
REMITTENCE_775 string 轉帳匯款(土城區農會)
REMITTENCE_776 string 轉帳匯款(三重區農會)
REMITTENCE_777 string 轉帳匯款(中和地區農會)
REMITTENCE_778 string 轉帳匯款(淡水區農會)
REMITTENCE_779 string 轉帳匯款(樹林區農會)
REMITTENCE_780 string 轉帳匯款(鶯歌區農會)
REMITTENCE_781 string 轉帳匯款(三峽區農會)
REMITTENCE_785 string 轉帳匯款(蘆洲區農會)
REMITTENCE_786 string 轉帳匯款(五股區農會)
REMITTENCE_787 string 轉帳匯款(林口區農會)
REMITTENCE_788 string 轉帳匯款(泰山區農會)
REMITTENCE_789 string 轉帳匯款(坪林區農會)
REMITTENCE_790 string 轉帳匯款(八里區農會)
REMITTENCE_791 string 轉帳匯款(金山地區農會)
REMITTENCE_792 string 轉帳匯款(瑞芳地區農會)
REMITTENCE_793 string 轉帳匯款(新店地區農會)
REMITTENCE_795 string 轉帳匯款(深坑區農會)
REMITTENCE_796 string 轉帳匯款(石碇區農會)
REMITTENCE_797 string 轉帳匯款(平溪區農會)
REMITTENCE_798 string 轉帳匯款(石門區農會)
REMITTENCE_799 string 轉帳匯款(三芝區農會)
REMITTENCE_803 string 轉帳匯款(聯邦銀行)
REMITTENCE_805 string 轉帳匯款(遠東銀行)
REMITTENCE_806 string 轉帳匯款(元大銀行)
REMITTENCE_807 string 轉帳匯款(永豐銀行)
REMITTENCE_808 string 轉帳匯款(玉山銀行)
REMITTENCE_809 string 轉帳匯款(凱基銀行)
REMITTENCE_810 string 轉帳匯款(星展銀行)
REMITTENCE_812 string 轉帳匯款(台新銀行)
REMITTENCE_814 string 轉帳匯款(大眾銀行)
REMITTENCE_815 string 轉帳匯款(日盛銀行)
REMITTENCE_816 string 轉帳匯款(安泰銀行)
REMITTENCE_822 string 轉帳匯款(中國信託)
REMITTENCE_823 string 轉帳匯款(將來銀行)
REMITTENCE_824 string 轉帳匯款(LINE Bank)
REMITTENCE_826 string 轉帳匯款(樂天銀行)
REMITTENCE_860 string 轉帳匯款(中埔鄉農會)
REMITTENCE_866 string 轉帳匯款(阿里山鄉農會)
REMITTENCE_868 string 轉帳匯款(東勢區農會)
REMITTENCE_869 string 轉帳匯款(清水區農會)
REMITTENCE_870 string 轉帳匯款(梧棲區農會)
REMITTENCE_871 string 轉帳匯款(大甲區農會)
REMITTENCE_872 string 轉帳匯款(沙鹿區農會)
REMITTENCE_874 string 轉帳匯款(霧峰區農會)
REMITTENCE_875 string 轉帳匯款(太平區農會)
REMITTENCE_876 string 轉帳匯款(烏日區農會)
REMITTENCE_877 string 轉帳匯款(后里區農會)
REMITTENCE_878 string 轉帳匯款(大雅區農會)
REMITTENCE_879 string 轉帳匯款(潭子區農會)
REMITTENCE_880 string 轉帳匯款(石岡區農會)
REMITTENCE_881 string 轉帳匯款(新社區農會)
REMITTENCE_882 string 轉帳匯款(大肚區農會)
REMITTENCE_883 string 轉帳匯款(外埔區農會)
REMITTENCE_884 string 轉帳匯款(大安區農會)
REMITTENCE_885 string 轉帳匯款(龍井區農會)
REMITTENCE_886 string 轉帳匯款(和平區農會)
REMITTENCE_891 string 轉帳匯款(花蓮市農會)
REMITTENCE_895 string 轉帳匯款(瑞穗鄉農會)
REMITTENCE_896 string 轉帳匯款(玉溪地區農會)
REMITTENCE_897 string 轉帳匯款(鳳榮地區農會)
REMITTENCE_898 string 轉帳匯款(光豐地區農會)
REMITTENCE_901 string 轉帳匯款(大里市農會)
REMITTENCE_902 string 轉帳匯款(苗栗市農會)
REMITTENCE_903 string 轉帳匯款(汐止農會)
REMITTENCE_904 string 轉帳匯款(新莊農會)
REMITTENCE_906 string 轉帳匯款(頭份市農會)
REMITTENCE_907 string 轉帳匯款(竹南鎮農會)
REMITTENCE_908 string 轉帳匯款(通霄鎮農會)
REMITTENCE_909 string 轉帳匯款(苑裡鎮農會)
REMITTENCE_910 string 轉帳匯款(聯資中心)
REMITTENCE_912 string 轉帳匯款(冬山農會)
REMITTENCE_913 string 轉帳匯款(後龍鎮農會)
REMITTENCE_914 string 轉帳匯款(卓蘭鎮農會)
REMITTENCE_915 string 轉帳匯款(西湖鄉農會)
REMITTENCE_916 string 轉帳匯款(草屯農會)
REMITTENCE_917 string 轉帳匯款(公館鄉農會)
REMITTENCE_918 string 轉帳匯款(銅鑼鄉農會)
REMITTENCE_919 string 轉帳匯款(三義鄉農會)
REMITTENCE_920 string 轉帳匯款(造橋鄉農會)
REMITTENCE_921 string 轉帳匯款(南庄鄉農會)
REMITTENCE_922 string 轉帳匯款(臺南農會)
REMITTENCE_923 string 轉帳匯款(獅潭鄉農會)
REMITTENCE_924 string 轉帳匯款(頭屋鄉農會)
REMITTENCE_925 string 轉帳匯款(三灣鄉農會)
REMITTENCE_926 string 轉帳匯款(大湖地區農會)
REMITTENCE_928 string 轉帳匯款(板橋農會)
REMITTENCE_929 string 轉帳匯款(關西鎮農會)
REMITTENCE_930 string 轉帳匯款(新埔鎮農會)
REMITTENCE_931 string 轉帳匯款(竹北市農會)
REMITTENCE_932 string 轉帳匯款(湖口鄉農會)
REMITTENCE_933 string 轉帳匯款(芎林鄉農會)
REMITTENCE_934 string 轉帳匯款(寶山鄉農會)
REMITTENCE_935 string 轉帳匯款(峨眉鄉農會)
REMITTENCE_936 string 轉帳匯款(北埔鄉農會)
REMITTENCE_937 string 轉帳匯款(竹東地區農會)
REMITTENCE_938 string 轉帳匯款(橫山地區農會)
REMITTENCE_939 string 轉帳匯款(新豐鄉農會)
REMITTENCE_940 string 轉帳匯款(新竹市農會信用部)
REMITTENCE_951 string 轉帳匯款(北農中心)
REMITTENCE_952 string 轉帳匯款(南部地區農漁會)
REMITTENCE_953 string 轉帳匯款(田尾鄉農會)
REMITTENCE_954 string 轉帳匯款(中部地區農漁會)
REMITTENCE_960 string 轉帳匯款(台灣樂天)
REMITTENCE_975 string 轉帳匯款(美國運通)
REMITTENCE_978 string 轉帳匯款(台灣永旺)
REMITTENCE_984 string 轉帳匯款(北投區農會)
REMITTENCE_985 string 轉帳匯款(士林區農會)
REMITTENCE_986 string 轉帳匯款(內湖區農會)
REMITTENCE_987 string 轉帳匯款(南港區農會)
REMITTENCE_988 string 轉帳匯款(木柵區農會)
REMITTENCE_989 string 轉帳匯款(景美區農會)
REMITTENCE_995 string 轉帳匯款(關貿網路)
REMITTENCE_996 string 轉帳匯款(財政部國庫署)
REMITTENCE_997 string 轉帳匯款(南資中心)
ALIPAY_YUANTABANK string 支付寶元大
ALIPAY_MEGABANK string 支付寶兆豐
ALIPAY_TCB string 支付寶合庫
WECHAT_SKBANK string 微信支付新光
MOMO string Momo收款
SHOPEE string 蝦皮拍賣收款
ETMALL string 東森收款
PCSTORE string PChome商店街收款
PCHOME24H string PChome24H收款
RUTEN string 露天拍賣收款
SHOPLINE string Shop line收款
FOODPANDA string 熊貓收款
UBEREATS string Uber eats收款
CYBERBIZ string Cyberbiz收款
YAHOOBID string YAHOO拍賣收款
RAKUTEN string 樂天市場收款
CAROUSELL string 旋轉拍賣收款
FACEBOOKGROUPS string FB社團收款
PINKOI string Pinkoi收款
91APP string 91APP收款
COD_MYPAY string MYPAY物流代收
COD_HCT string 新竹物流代收
COD_TCAT string 黑貓宅急便代收
COD_MYSHIP711 string 7-ELEVEN賣貨便代收
COD_FAMISTORE string 好賣+代收
COD_HISHIPBUYER string 萊賣貨代收
COD_KERRYTJ string 嘉里大榮代收
CSTORECODE_IBON string 超商代碼(IBON)
CSTORECODE_FAMIPORT string 超商代碼(FamiPort)
CSTORECODE_LIFEET string 超商代碼(Life-ET)
CSTORECODE_OKGO string 超商代碼(OK GO)
ETICKET_EASYCARD string 悠遊卡
ETICKET_IPASS string 一卡通
ETICKET_ICASH string iCash
CRYPTO_BTC string 比特幣
CRYPTO_ETH string 乙太幣
TELECOM_CHT string 中華電信代收
TELECOM_FET string 遠傳電信代收
TELECOM_TWM string 台灣大哥大代收
TELECOM_TSTAR string 台灣之星代收
TELECOM_APT string 亞太電信代收
ECPAY_CREDIT string 綠界收款(信用卡)
ECPAY_WEBATM string 綠界收款(網路ATM)
ECPAY_ATM string 綠界收款(自動櫃員機)
ECPAY_CVS string 綠界收款(超商代碼)
ECPAY_BARCODE string 綠界收款(超商條碼)
ECPAY_TWQR string 綠界收款(行動支付)
ECPAY_IN_STORE_PICKUP string 綠界收款(超取)
NEWEBPAY_CREDIT string 藍新收款(信用卡付款)
NEWEBPAY_VACC string 藍新收款(銀行 ATM 轉帳付款)
NEWEBPAY_WEBATM string 藍新收款(網路銀行轉帳付款)
NEWEBPAY_BARCODE string 藍新收款(超商條碼繳費)
NEWEBPAY_CVS string 藍新收款(超商代碼繳費)
NEWEBPAY_LINEPAY string 藍新收款(LINE Pay 付款)
NEWEBPAY_ESUNWALLET string 藍新收款(玉山 Wallet)
NEWEBPAY_TAIWANPAY string 藍新收款(台灣 Pay)
NEWEBPAY_CVSCOM string 藍新收款(超商取貨付款)
CREDITCARD_TCB string 信用卡(合庫銀行)
CREDITCARD_ESUNBANK string 信用卡(玉山銀行)
CREDITCARD_FIRSTBANK string 信用卡(第一銀行)
CREDITCARD_FUBONBANK string 信用卡(台北富邦銀行)
CREDITCARD_TSIB string 信用卡(台新銀行)
CREDITCARD_NCCC string 信用卡(聯信)
CREDITCARD_CTBC string 信用卡(中信銀行)
CREDITCARD_KGIBANK string 信用卡(凱基銀行)
CREDITCARD_YUANTABANK string 信用卡(元大銀行)
CREDITCARD_CUB string 信用卡(國泰世華銀行)
CREDITCARD_BANKSINOPAC string 信用卡(永豐銀行)
CREDITCARD_MEGABANK string 信用卡(兆豐銀行)
CREDITCARD_GLOBALPAYMENTS string 信用卡(環匯亞太)
AMEX_TSIB string 美國運通(台新銀行)
AMEX_CTBC string 美國運通(中信銀行)
AMEX_NCCC string 美國運通(聯信)
UNIONPAY_TCB string 銀聯卡(合庫銀行)
UNIONPAY_ESUNBANK string 銀聯卡(玉山銀行)
UNIONPAY_NCCC string 銀聯卡(聯信)
UNIONPAY_TSIB string 銀聯卡(台新銀行)
UNIONPAY_KGIBANK string 銀聯卡(凱基銀行)
UNIONPAY_YUANTABANK string 銀聯卡(元大銀行)
UNIONPAY_BANKSINOPAC string 銀聯卡(永豐銀行)
UNIONPAY_CUB string 銀聯卡(國泰世華銀行)
BARCODE_SKBANK string 超商繳費條碼(新光銀行)
BARCODE_ESUNBANK string 超商繳費條碼(玉山銀行)
BARCODE_CTBC string 超商繳費條碼(中信銀行)
TWPAY_BOT string 台灣Pay(台灣銀行)
TWPAY_LANDBANK string 台灣Pay(台灣土地銀行)
TWPAY_TCB string 台灣Pay(合庫銀行)
TWPAY_FIRSTBANK string 台灣Pay(第一銀行)
TWPAY_HNCB string 台灣Pay(華南銀行)
TWPAY_CHB string 台灣Pay(彰化銀行)
TWPAY_SCSB string 台灣Pay(上海商銀)
TWPAY_CUB string 台灣Pay(國泰世華銀行)
TWPAY_MEGABANK string 台灣Pay(兆豐銀行)
TWPAY_BOK string 台灣Pay(高雄銀行)
TWPAY_TBB string 台灣Pay(台灣企銀)
TWPAY_KTB string 台灣Pay(京城銀行)
TWPAY_HWATAIBANK string 台灣Pay(華泰銀行)
TWPAY_SUNNYBANK string 台灣Pay(陽信銀行)
TWPAY_KSCC string 台灣Pay(基隆二信)
TWPAY_TFCCBANK string 台灣Pay(淡水一信)
TWPAY_HCFCBANK string 台灣Pay(新竹一信)
TWPAY_TSCA string 台灣Pay(台中二信)
TWPAY_CH6C string 台灣Pay(彰化六信)
TWPAY_HL2C string 台灣Pay(花蓮二信)
TWPAY_ESUNBANK string 台灣Pay(玉山銀行)
TWPAY_TSIB string 台灣Pay(台新銀行)
TWPAY_AFISC string 台灣Pay(農金資)
TWPAY_YUANTABANK string 台灣Pay(元大銀行)
TWPAY_CTBC string 台灣Pay(中信銀行)
TWPAY_FAST string 台灣Pay(南農中心)
TWPAY_SCU string 台灣Pay(南資中心)
DS_SHINSHIN string 欣欣大眾
DS_MINGYAO string 明曜百貨
DS_DAYEH string 大葉高島屋
DS_CHUNGYO string 中友百貨
DS_KSSOGO string 廣三SOGO百貨
DS_FOCUSQUARE string Focus時尚流行館
DS_NICEPLAZA string 耐斯廣場
DS_DREAMMALL string 夢時代購物中心
DS_UNIUSTYLE string 統一時代百貨
DS_PARKLANES string 金典綠園道商場
DS_CITYPLAZA string 大都會廣場
DS_LIHPAOMALL string 麗寶百貨廣場
DS_EDORAPARK string 瀚星百貨
DS_BEYONDPLAZA string 比漾廣場
DS_HAYASHI string 林百貨
DS_SHINESQUARE string 昕境廣場
DS_LANDMARKLIFEPLAZA string 置地生活廣場
DS_TONLIN string 統領廣場
DS_HONHUI string 宏匯廣場
DS_TSRD string 南紡購物中心
DS_FEDS_XINYIA13 string 遠東百貨-遠百信義 A13
DS_FEDS_BANQIAO string 遠東百貨-板橋中山店
DS_FEDS_TAOYUAN string 遠東百貨-桃園店
DS_FEDS_ZHUPEI string 遠東百貨-竹北店
DS_FEDS_CHIAYI string 遠東百貨-嘉義店
DS_FEDS_HUALIEN string 遠東百貨-花蓮店
DS_FEDS_MEGACITY_BANQIAO string 遠東百貨-MegaCity板橋大遠百
DS_FEDS_HSINCHU string 遠東百貨-新竹大遠百
DS_FEDS_TOPCITY_TAICHUNG string 遠東百貨-Top City台中大遠百
DS_FEDS_TAINAN_GONGYUAN string 遠東百貨-台南大遠百公園店
DS_FEDS_TAINAN_CHENGKUNG string 遠東百貨-台南大遠百成功店
DS_FEDS_KAOHSIUNG string 遠東百貨-高雄大遠百
DS_SKM_XINYI string 新光三越-台北信義新天地
DS_SKM_TAIPEI_STATION string 新光三越-台北站前店
DS_SKM_TAIPEI_NANJING_W string 新光三越-台北南西店
DS_SKM_TAIPEI_TIANMU string 新光三越-台北天母店
DS_SKM_TAOYUAN_STATION string 新光三越-桃園站前店
DS_SKM_TAICHUNG_PORT string 新光三越-台中中港店
DS_SKM_CHIAYI_CHUIYANG string 新光三越-嘉義垂楊店
DS_SKM_TAINAN_ZHONGSHAN string 新光三越-台南中山店
DS_SKM_TAINAN_XIMEN string 新光三越-台南西門店
DS_SKM_KAOHSIUNG_SANDUO string 新光三越-高雄三多店
DS_SKM_KAOHSIUNG_ZUOYING string 新光三越-高雄左營店
DS_SKM_PARK string 新光三越-SKM Park Outlets 高雄草衙
DS_SOGO_TAIPEI_ZHONGXIAO string 遠東SOGO百貨-台北忠孝館
DS_SOGO_TAIPEI_FUXING string 遠東SOGO百貨-台北復興館
DS_SOGO_TAIPEI_DUNHUA string 遠東SOGO百貨-台北敦化館
DS_SOGO_TIANMU string 遠東SOGO百貨-天母店
DS_SOGO_ZHONGLI string 遠東SOGO百貨-中壢店
DS_SOGO_HSINCHU string 遠東SOGO百貨-新竹店
DS_SOGO_KAOHSIUNG string 遠東SOGO百貨-高雄店
DS_PACIFIC_FENGYUAN string 太平洋百貨-豐原
DS_PACIFIC_PINGTUNG string 太平洋百貨-屏東
DS_PACIFIC_SUNNYPARK string 太平洋百貨-Sunny Park日光廣場
DS_PACIFIC_PINGTUNG_GONGYONG string 太平洋百貨-屏東驛站商場
DS_PACIFIC_PINGTUNG_GUANGFU string 太平洋百貨-屏東轉運站商場
DS_PACIFIC_CHAOZHOU string 太平洋百貨-潮州驛站商場
DS_HANSHIN_KAOHSIUNG string 漢神百貨
DS_HANSHIN_ARENA string 漢神巨蛋購物廣場
DS_BREEZE_CENTER string 微風廣場
DS_BREEZE_TAIPEISTATION string 微風台北車站
DS_BREEZE_NTUHOSPITAL string 微風台大醫院商場
DS_BREEZE_NANJING string 微風南京
DS_BREEZE_XINYI string 微風信義
DS_BREEZE_SONGGAO string 微風松高
DS_BREEZE_NANSHAN string 微風南山
DS_BREEZE_TSGHOSPITAL string 微風三總商店街
DS_BREEZE_ACADEMIASINICA string 微風中央研究院
DS_GM_ZHONGHE string GlobalMall-新北中和
DS_GM_BANQIAO string GlobalMall-環球板橋車站
DS_GM_A8 string GlobalMall-環球桃園A8
DS_GM_A19 string GlobalMall-環球桃園A19
DS_GM_A9 string GlobalMall-環球林口A9
DS_GM_NANGANG string GlobalMall-環球南港車站
DS_GM_XINZUOYING string GlobalMall-環球新左營車站
DS_GM_PINGTUNG string GlobalMall-環球屏東市
DS_TRK_MALL string 大魯閣新時代購物中心
DS_TRK_SQUARE string 大魯閣湳雅廣場
DS_TALEE_WUFU string 大立大統五福店
DS_TALEE_A string 大立百貨A館
DS_TALEE_B string 大立百貨B館
DS_MITSUI_OUTLET_TAICHUNGPORT string MITSUI OUTLET PARK 台中港
DS_MITSUI_OUTLET_TAINAN string MITSUI OUTLET PARK 台南
DS_MITSUI_OUTLET_LINKOU string MITSUI OUTLET PARK 林口
DS_MITSUI_LALAPORT_TAICHUNG string Mitsui Shopping Park LaLaport 台中

附錄一:PFN(支付工具)參數表

資料傳遞可使用編號,也可以使用代碼 。 例如:pfn=27跟pfn=PION,一樣都是使用Pi 拍錢包線上付款支付工具。

編號 代碼 狀態 說明
1 CREDITCARD 啟用 信用卡
3 CSTORECODE 啟用 超商代碼
4 WEBATM 啟用 WEBATM
6 E_COLLECTION 啟用 虛擬帳號 (ATM轉帳)
7 UNIONPAY 啟用 銀聯卡
9 ABROAD 啟用 海外信用卡(非台灣發行信用卡)
10 ALIPAY 啟用 支付寶
13 WECHAT 啟用 微信支付
14 DIRECTDEBIT 啟用 定期扣款
15 LINEPAYON 啟用 LINE線上付款(消費者主掃)
16 LINEPAYOFF 啟用 LINE線下付款(消費者被掃)
19 WECHATOFF 啟用 微信支付線下
20 APPLEPAY 啟用 Apple Pay
21 GOOGLEPAY 啟用 Google Pay
22 EACH 啟用 eACH
23 C_INSTALLMENT 啟用 信用卡分期
24 C_REDEEM 啟用 信用卡紅利
25 CARDLESS 啟用 無卡分期(由資融公司提供分期服務)
27 PION 啟用 Pi 拍錢包線上付款(消費者主掃)
28 PIOFF 啟用 Pi 拍錢包線下付款(消費者被掃)
29 AMEX 啟用 美國運通
31 JKOON 啟用 街口支付線上付款(消費者主掃)
32 JKOOF 啟用 街口支付線下付款(消費者被掃)
33 ALIPAYOFF 啟用 支付寶線下(消費者被掃)
36 AFP 啟用 後付款
37 CASH 啟用 現金
38 EASYWALLETON 啟用 悠遊付線上付款(消費者主掃)
39 EASYWALLETOFF 啟用 悠遊付線下付款(消費者被掃)
40 EASYCARD 啟用 悠遊卡
41 IPASS 啟用 一卡通
42 ICASH 啟用 iCash
43 BARCODE 啟用 超商條碼繳費
46 PXPAYOFF 啟用 全支付線下(消費者被掃)

附錄二:交易狀態代碼

以下回傳的狀態代碼均須處理,避免系統連線錯誤,MYPAY LINK回傳時,貴司系統無法判讀

狀態代碼 狀態說明 詳細說明
100 資料錯誤 MYPAYLINK收到資料,但是格式或資料錯誤
200 資料正確 MYPAYLINK收到正確資料,會接續下一步交易

220 取消成功 如申請取消,取消訂單狀態為取消成功
230 退款成功 如申請退款,申請退款成功時狀態。
245 授權成功 若使用信用卡類自行請款模式,則交易後為授權成功。之後進行請款動作,才會轉為付款成功(250)
247 請款進行中 若使用信用卡類自行請款模式,閘道為玉山或NCCC(聯信、凱基、元大)等批次處理,發動請款時轉為此狀態,等候金融服務商通知請款成功,才會轉為付款成功(250)
250 付款成功 此次交易,消費者付款成功
260 交易成功
尚未付款完成
超商代碼繳費-請等候消費者繳費入帳完成付款或消費者放棄交易,MYPAY LINK會再傳送一次結果:
250:代表消費者付款成功,此為最終結果
380:代表消費者沒有在時限內去繳費,逾期未去繳費,視同交易失敗,此為最終結果
265 訂單綁定 表示訂單編號生效,進入貸款頁面,但尚未註冊
最後會在回傳狀態
A0002:消費者放棄該筆交易,該筆交易視同交易失敗,為最終結果
275:無卡分期-請等候審查通過
270 交易成功
尚未付款完成
虛擬帳號-請等候消費者繳費入帳
完成付款或消費者放棄交易,MYPAY LINK會再傳送一次結果:
250:代表消費者付款成功,此為最終結果
380:代表消費者沒有在時限內去繳費,逾期未去繳費,視同交易失敗,此為最終結果
280 交易成功
尚未付款完成
儲值/WEBATM-線上待付款,等待狀態,等到使用者線上完成交易後MYPAY LINK會再傳送一次結果
250:代表消費者付款成功,此為最終結果
300:代表消費者付款失敗
282 訂單成立待後付款審核確認
尚未付款完成
後付款,等待狀態,等後付款審核通過通知
284:代表後付款審核通過
300:代表審核不通過
284 訂單成立後付款待請款
尚未付款完成
後付款,等待狀態,等特約商店出貨後,需發動請款告知後付款已出貨請款
250:代表後付款請款成功,此為最終結果
300:代表後付款請款失敗
290 交易成功
但資訊不符
交易成功,但資訊不符(包含金額不符,如多繳或少繳...等),該類型交易請特別注意

300 交易失敗 金流服務商回傳交易失敗或該筆交易超過風險控管限制規則
380 逾期交易 超商代碼或虛擬帳號交易,超過系統設定繳費期限
若經MYPAY LINK查詢驗證後,有機會在變更狀態
290:交易成功,但資訊不符
原因有可能是服務商的參數規則漏洞或是系統時間差異造成
400 系統錯誤訊息 若MYPAY LINK或上游服務商系統異常時
600 結帳完成 視為付款完成,此狀態為上游服務商確認訂單後的狀態,表示該筆訂單會撥款
透過MYPAY主動查詢或每日對帳機制
操作訂單功能內發動查詢功能
A0001 交易待確認 MYPAY LINK與金流服務商發生連線異常,待查詢後確認結果,會主動再次回傳交易結果
250:代表消費者確實付款完成
600:結帳完成
300:金流服務商回傳交易失敗或超過風險控管限制規則交易
A0002 放棄交易 畫面導向MYPAY LINK後,消費者即放棄該筆交易,該筆交易視同交易失敗,為最終結果
B200 執行成功 處理成功執行
B500 執行失敗 處理時,資料異常不予以處理

附錄三:設定調整

附錄四:資料加密方式說明

  1. 所有的API送出HTTPs請求之欄位中,service 和 encry_data 欄位皆進行 AES256+BASE64 加密處理。
  2. AES加密,格式為CBC,長度為256bits,金鑰長度32,IV長度16,傳遞內文為加密後組合IV並經過Base64轉換後傳出。
  3. IV資料建議隨機產生。

附錄五:API模擬串接服務

提供模擬使用HTTP Protocol,透過POST方式傳遞資料到MYPAY, 並且得到回傳結果。

附錄六:測試區測試用信用卡卡號

下面卡號僅限在測試區測試使用

聯合信用卡中心閘道(其中MasterCard/JCB可測分期與紅利)

Visa MasterCard JCB
卡號 4938170130000003 5430450100001219 3560500100001218
有效日期 1228 1218 1218
安全碼 985 214 023
3D交易密碼 nccc1234

永豐銀行信用卡

Visa MasterCard JCB
卡號 4058650600065507 5433760200078009 3566703300032801
有效日期 1022 1022 0922
安全碼 395 597 033

中國信託信用卡 (使用電子錢包功能適用)

Visa
一般交易 4003618704777729
有效日期 任意
安全碼 任意
3D交易密碼 1234567

高鉅模擬信用卡(成功卡)

Visa MasterCard JCB
一般交易 4761120010000492 5204247750001471 3566703300032801
有效日期 1122 1122 0922
安全碼 533 111 033

高鉅模擬信用卡(失敗卡)

MasterCard
一般交易 5204247750001471
有效日期 1122
安全碼 111

高鉅模擬信用卡(3D)

說明 卡號
3D交易 4003618704777729
有效日期 任意
安全碼 任意

凱基 (醫療費/捐款費用) 信用卡

Visa
一般交易 4907060600015101
有效日期 1226
安全碼 905

備註:(醫療費/捐款費用)信用卡所使用之訂單編號「order_id」(繳費單號)長度最長為16bytes。(此為上游限制)

附錄七:測試區測試用線下交易支付碼

下面支付碼僅限在測試區測試使用

1.街口支付線下

說明 支付碼
二維條碼 22J111111111111111

2.全支付線下

說明 支付碼
二維條碼 P1M281A4C00B2JOO1N

3.LINEPay線下

說明 支付碼產生連結
二維條碼 https://sandbox-web-pay.line.me/web/sandbox/payment/oneTimeKey?countryCode=TW&paymentMethod=card&point=20

上述支付方式為通用測試支付碼,其餘須依向服務商帳號申請之相關Sandbox模式進行測試。

附錄八:交易背景通知回報欄位

『交易完成回傳資訊』回報欄位

參數名稱 型態 說明 必須
uid string Payment Hub之交易流水號
key string 交易驗証碼
prc string 主要交易回傳碼(retcode)
finishtime string 交易完成時間(YYYYMMDDHHmmss)
cardno string 銀行端口回傳碼
acode string 授權碼
card_type string 信用卡卡別 『信用卡別類型』值參考
issuing_bank string 發卡行
issuing_bank_uid string 發卡銀行代碼
is_agent_charge int 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer 交易服務類型 『交易服務類型』值參考
supplier_name string 交易之金融服務商
supplier_code string 交易之金融服務商代碼 『金流供應商代碼』值參考
order_id string 貴特店系統的訂單編號
user_id string 消費者帳號
cost string 總交易金額
currency string 原交易幣別
actual_cost string 實際交易金額
actual_currency string 實際交易幣別
price string 請求交易點數/金額
actual_price string 實際交易點數/金額
recharge_code string 交易產品代碼
love_cost string 愛心捐款金額
retmsg string 回傳訊息
pfn string 付費方法
trans_type integer 交易類型 『交易類型定義』值參考
redeem string 紅利資訊 JSON 格式 『紅利資訊』值參考
installment string 信用卡分期資訊 JSON 格式 『分期資訊』值參考
payment_name string 定期定額式/定期分期式扣款名稱
nois string 定期定額式/定期分期式扣繳期數
group_id string 1.定期定額式扣款編號
2.定期分期式扣款編號
bank_id string 銀行代碼
虛擬帳號資訊
expired_date string 有效日期(YYYYMMDDHHmmss)
虛擬帳號、超商代碼、無卡分期資訊
result_type integer 虛擬帳號、超商代碼 資料格式類型 『閘道內容回傳格式類型』值參考
result_content_type string 資料內容所屬支付名稱 『資料內容所屬支付名稱』值參考
result_content string 虛擬帳號、超商代碼 資料內容 『虛擬帳號回傳欄位』值參考
『ibon』值參考
『FamiPort』值參考
『Life-ET』值參考
『超商條碼繳費』值參考
echo_0 string 自訂回傳參數 1
echo_1 string 自訂回傳參數 2
echo_2 string 自訂回傳參數 3
echo_3 string 自訂回傳參數 4
echo_4 string 自訂回傳參數 5

『非即時交易回傳資訊』回報欄位

參數名稱 型態 說明 必須
uid string Payment Hub之交易流水號
key string 交易驗証碼
prc string 主要交易回傳碼(retcode)
cardno string 銀行端口回傳碼
acode string 授權碼
card_type string 信用卡卡別 『信用卡別類型』值參考
issuing_bank string 發卡行
issuing_bank_uid string 發卡銀行代碼
is_agent_charge int 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer 交易服務類型 『交易服務類型』值參考
supplier_name string 交易之金融服務商
supplier_code string 交易之金融服務商代碼 『金流供應商代碼』值參考
finishtime string 交易完成時間(YYYYMMDDHHmmss)
order_id string 貴特店系統的訂單編號
user_id string 消費者帳號
cost string 總交易金額
currency string 原交易幣別
actual_cost string 實際交易金額
actual_currency string 實際交易幣別
price string 請求交易點數/金額
actual_price string 實際交易點數/金額
recharge_code string 交易產品代碼
love_cost string 愛心捐款金額
retmsg string 回傳訊息
pfn string 付費方法
trans_type integer 交易類型 『交易類型定義』值參考
redeem string 紅利資訊 JSON 格式 『紅利資訊』值參考
installment string 信用卡分期資訊 JSON 格式 『分期資訊』值參考
payment_name string 定期定額式/定期分期式扣款名稱
nois string 定期定額式/定期分期式扣繳期數
group_id string 1.定期定額式扣款編號
2.定期分期式扣款編號
bank_id string 銀行代碼
虛擬帳號資訊
expired_date string 有效日期(YYYYMMDDHHmmss)
虛擬帳號、超商代碼、無卡分期資訊
result_type integer 虛擬帳號、超商代碼 資料格式類型 『閘道內容回傳格式類型』值參考
result_content_type string 資料內容所屬支付名稱 『資料內容所屬支付名稱』值參考
result_content string 虛擬帳號、超商代碼 資料內容 『虛擬帳號回傳欄位』值參考
『ibon』值參考
『FamiPort』值參考
『Life-ET』值參考
echo_0 string 自訂回傳參數 1
echo_1 string 自訂回傳參數 2
echo_2 string 自訂回傳參數 3
echo_3 string 自訂回傳參數 4
echo_4 string 自訂回傳參數 5

『訂單確認回傳資訊』回報欄位

參數名稱 型態 說明 必須
uid string Payment Hub之交易流水號
key string 交易驗証碼
prc string 主要交易回傳碼(retcode)
finishtime string 交易完成時間(YYYYMMDDHHmmss)
cardno string 銀行端口回傳碼
acode string 授權碼
card_type string 信用卡卡別 『信用卡別類型』值參考
issuing_bank string 發卡行
issuing_bank_uid string 發卡銀行代碼
is_agent_charge int 是否為經銷商代收費模式 『是否為經銷商代收費模式』值參考
transaction_mode integer 交易服務類型 『交易服務類型』值參考
supplier_name string 交易之金融服務商
supplier_code string 交易之金融服務商代碼 『金流供應商代碼』值參考
order_id string 貴特店系統的訂單編號
user_id string 消費者帳號
cost string 總交易金額
currency string 原交易幣別
actual_cost string 實際交易金額
actual_currency string 實際交易幣別
price string 請求交易點數/金額
actual_price string 實際交易點數/金額
recharge_code string 交易產品代碼
love_cost string 愛心捐款金額
retmsg string 回傳訊息
pfn string 付費方法
trans_type integer 交易類型 『交易類型定義』值參考
redeem string 紅利資訊 JSON 格式 『紅利資訊』值參考
installment string 信用卡分期資訊 JSON 格式 『分期資訊』值參考
payment_name string 定期定額式/定期分期式扣款名稱
nois string 定期定額式/定期分期式扣繳期數
group_id string 1.定期定額式扣款編號
2.定期分期式扣款編號
bank_id string 銀行代碼
虛擬帳號資訊
expired_date string 有效日期(YYYYMMDDHHmmss)
虛擬帳號、超商代碼、無卡分期資訊
result_type integer 虛擬帳號、超商代碼 資料格式類型 『閘道內容回傳格式類型』值參考
result_content_type string 資料內容所屬支付名稱 『資料內容所屬支付名稱』值參考
result_content string 虛擬帳號、超商代碼 資料內容 『虛擬帳號回傳欄位』值參考
『ibon』值參考
『FamiPort』值參考
『Life-ET』值參考
echo_0 string 自訂回傳參數 1
echo_1 string 自訂回傳參數 2
echo_2 string 自訂回傳參數 3
echo_3 string 自訂回傳參數 4
echo_4 string 自訂回傳參數 5