服务端 Webhook

PHP Webhook

对于使用 php 的 Opencard 应用, 开发者可以参考以下 php 示例代码,来实现 Webhook 服务。

  1. /* jwt 库
    * github地址:https://github.com/kelvinmo/simplejwt
    * 假设克隆后文件夹名为:simplejwt-master
    */
    <?php
    //此处仅加载本需求使用到的文件
    require_once "./simplejwt-master/src/SimpleJWT/Crypt/EncryptionAlgorithm.php";
    require_once "./simplejwt-master/src/SimpleJWT/Crypt/KeyManagementAlgorithm.php";
    require_once "./simplejwt-master/src/SimpleJWT/Crypt/Algorithm.php";
    require_once "./simplejwt-master/src/SimpleJWT/Crypt/KeyEncryptionAlgorithm.php";
    require_once "./simplejwt-master/src/SimpleJWT/Crypt/AESCBC_HMACSHA2.php";
    require_once "./simplejwt-master/src/SimpleJWT/Crypt/AESKeyWrap.php";
    require_once "./simplejwt-master/src/SimpleJWT/Crypt/AlgorithmFactory.php";
    require_once "./simplejwt-master/src/SimpleJWT/JWE.php";
    require_once "./simplejwt-master/src/SimpleJWT/Keys/KeySet.php";
    require_once "./simplejwt-master/src/SimpleJWT/Util/Util.php";
    require_once "./simplejwt-master/src/SimpleJWT/Keys/Key.php";
    require_once "./simplejwt-master/src/SimpleJWT/Crypt/CryptException.php";
    require_once "./simplejwt-master/src/SimpleJWT/InvalidTokenException.php";
    require_once "./simplejwt-master/src/SimpleJWT/Keys/SymmetricKey.php";
    require_once "./simplejwt-master/src/SimpleJWT/Crypt/KeyDerivationAlgorithm.php";
    /* Webhook 基本协议实现
    *
    * 以下代码为示例,未妥善处理业务字段或异常等因素
    */
    public function execute(){
    # 配置项,测试时请修改以下配置
    $arrPsks = array("MDEyMzQ1Njc4OWFiY2RlMQ");

    //组建自己的 PSK_TABLE, 可根据自己的需求修改
    $psk_table = array();
    foreach ($arrPsks as $key => $strPsk) {
    $strKey = strval($key);
    $keys = new \SimpleJWT\Keys\KeySet();
    $pskKey = new \SimpleJWT\Keys\SymmetricKey($strPsk, 'base64url');
    $pskKey->setKeyId($strKey);
    $keys->add($pskKey);
    $psk_table[$strKey] = $keys;
    }
    $alg = "A128KW";

    //获取到请求数据
    $token = file_get_contents ('php://input');

    //解析请求数据
    $parts = explode('.', $token, 5);
    if (count($parts) != 5) {
    throw new InvalidTokenException('Cannot decode compact serialisation', InvalidTokenException::TOKEN_PARSE_ERROR);
    }
    list($protected, $encrypted_key, $iv, $ciphertext, $tag) = $parts;

    //解析出 header
    $jose_header = json_decode(\SimpleJWT\Util\Util::base64url_decode($protected), true);

    //从 protected 字段中解出来 kid
    $kid = $jose_header['kid'];

    //通过 kid 确定要使用哪个解密 key
    $psk = $psk_table[strval($kid)];

    //用 key 解密取得解密后的内容
    $jwe = \SimpleJWT\JWE::decrypt($token,$psk,$alg);
    $req = json_decode( $jwe->getPlaintext(), true);

    //如果资源方有多张卡片,从 req 中解析出来 srcid,处理相应的业务逻辑
    if ($req['srcid'] == "123"){
    //do something
    $res = array(
    'status' => 0,
    'msg' => "",
    );
    $res['data'] = array(
    'item_list' => array(
    'title' => "故宫博物院",
    'jump_url' => "/path/to/pages3",
    ),
    );
    } else {
    $res = array(
    'status' => 2,
    'msg' => "Invalid srcid",
    );
    }

    //处理业务响应结果
    $playload = json_encode($res);

    //用请求的 header 和 key 生成加密结果,保持加密算法和头内容(kid/rid)与请求一致
    $jwe = new \SimpleJWT\JWE($jose_header, $playload);
    $res_body = $jwe->encrypt($psk);

    header("Content-type:application/jwt; charset=UTF-8");
    echo ($res_body);
    }