View Issue Details

IDProjectCategoryView StatusLast Update
0011542Talerchallengerpublic2026-11-03 14:06
ReporterChristian Grothoff Assigned ToResolution deadline
ImplementerChristian Grothoff ReviewerFlorian Dold  
Release signed byChristian Grothoff Deployed byFlorian Dold  
VerifierChristian Grothoff Communicator 
Data protection authority notification requiredNo  
CSIRT notification requiredNo  
Estimated effort (hours)2Actual effort (hours)0.28 
Fast-trackNo
Work packagenone
PrioritynormalSeverityfeatureReproducibilityN/A
Status reviewingResolutionopen 
Platformi7OSDebian GNU/LinuxOS Versionsqueeze
Product Versiongit (master) 
Target Version1.6 
Summary0011542: support Swiss aspsms.com SMS provider
DescriptionBasically same cost, and local provider. We should add a 3rd shell script to our set.
TagsNo tags attached.

Required notifications

Address or linkRemarkAdded byNotifiedActions

Activities

Christian Grothoff

2026-06-26 08:36

manager   ~0028986

Draft script (to be tested once we have credentials) attached.
aspsms.sh (4,414 bytes)   
#!/bin/bash
#
# send-sms.sh
#
# Usage:
#   echo "Hello world" | ./send-sms.sh +41791234567
#
# Environment:
#   ASPSMS_USERKEY
#   ASPSMS_PASSWORD
#
# Exit codes:
#
#   0  SMS delivered
#
#   1  Usage/configuration error
#   2  Local/network/API communication failure
#   3  ASPSMS authentication failure
#   4  Invalid phone number
#   5  Recipient unavailable (phone off / no coverage / expired)
#   6  Mobile operator/provider failure
#   7  ASPSMS rejected request
#   8  Delivery timeout (status never became final)
#   9  Unknown failure
#

set -euo pipefail

API="https://webapi.aspsms.com"

if [[ $# -ne 1 ]]
then
    echo "Usage: $0 PHONE_NUMBER" >&2
    exit 1
fi

: "${ASPSMS_USERKEY:?ASPSMS_USERKEY not set}"
: "${ASPSMS_PASSWORD:?ASPSMS_PASSWORD not set}"

PHONE="$1"
MESSAGE="$(cat -)"

if [[ -z "$MESSAGE" ]]
then
    echo "Empty message" >&2
    exit 1
fi

TRANSREF="$(date +%s)-$$-$RANDOM"

#
# Send SMS
#
SEND_JSON="$(
curl -fsS \
    --get \
    "$API/SendSimpleSMS" \
    --data-urlencode "Userkey=$ASPSMS_USERKEY" \
    --data-urlencode "Password=$ASPSMS_PASSWORD" \
    --data-urlencode "Recipient=$PHONE" \
    --data-urlencode "MessageData=$MESSAGE" \
    --data-urlencode "TransactionReferenceNumber=$TRANSREF"
)" || {
    echo "Communication with ASPSMS failed" >&2
    exit 2
}

ERROR_CODE=$(jq -r '.ErrorCode // empty' <<<"$SEND_JSON")
ERROR_DESC=$(jq -r '.ErrorDescription // empty' <<<"$SEND_JSON")

case "$ERROR_CODE" in
    1)
        ;;
    3|8|9)
        echo "$ERROR_DESC" >&2
        exit 3
        ;;
    20|206)
        echo "$ERROR_DESC" >&2
        exit 4
        ;;
    24)
        echo "$ERROR_DESC" >&2
        exit 7
        ;;
    "")
        echo "Unexpected response:" >&2
        echo "$SEND_JSON" >&2
        exit 2
        ;;
    *)
        echo "$ERROR_DESC" >&2
        exit 7
        ;;
esac

#
# Poll delivery status
#
#
# DeliveryStatus:
#   -1 not yet known
#    0 delivered
#    1 buffered
#    2 failed
#
# Reason codes of interest:
#
# 000 unknown subscriber
# 101 unknown subscriber
# 107 absent subscriber
# 108 delivery failed
# 105/113 SC congestion
# 118-126 network/provider failures
# 206 invalid destination address
#

for ((i=0;i<60;i++))
do
    SEC=$(expr $i / 10)
    # Wait at least 100ms, then go up every second by 1 second
    sleep $SEC.1
    STATUS_JSON="$(
    curl -fsS \
        --get \
        "$API/SendingStat03/Get" \
        --data-urlencode "Userkey=$ASPSMS_USERKEY" \
        --data-urlencode "Password=$ASPSMS_PASSWORD" \
        --data-urlencode "TransactionReferenceNumber=$TRANSREF"
    )" || continue

    DELIVERY=$(jq -r '.[0].DeliveryStatus // empty' <<<"$STATUS_JSON")
    REASON=$(jq -r '.[0].ReasonCode // ""' <<<"$STATUS_JSON")

    case "$DELIVERY" in

        0)
            exit 0
            ;;

        1)
            continue
            ;;

        2)
            case "$REASON" in

                206|000|101)
                    exit 4
                    ;;

                107|108)
                    exit 5
                    ;;

                105|113|118|119|120|121|122|123|124|125|126)
                    exit 6
                    ;;

                *)
                    exit 9
                    ;;
            esac
            ;;

        -1|"")
            continue
            ;;

    esac

done

exit 8

#| Exit | Meaning                                                                       |
#| ---- | ----------------------------------------------------------------------------- |
#| 0    | SMS successfully delivered                                                    |
#| 1    | Usage or local configuration error                                            |
#| 2    | Unable to contact ASPSMS/API/network error                                    |
#| 3    | Authentication failure (invalid user key/password)                            |
#| 4    | Invalid or unknown recipient number                                           |
#| 5    | Recipient unreachable (phone switched off, out of coverage, delivery expired) |
#| 6    | Mobile operator/network/provider failure                                      |
#| 7    | ASPSMS rejected the request (temporary service issues, invalid request, etc.) |
#| 8    | Timed out waiting for a final delivery report                                 |
#| 9    | Delivery failed for an unclassified reason                                    |
aspsms.sh (4,414 bytes)   

Christian Grothoff

2026-06-26 08:55

manager   ~0028987

Debugging... still fails.
aspsms-2.sh (4,430 bytes)   
#!/bin/bash
#
# send-sms.sh
#
# Usage:
#   echo "Hello world" | ./send-sms.sh +41791234567
#
# Environment:
#   ASPSMS_USERKEY
#   ASPSMS_PASSWORD
#
# Exit codes:
#
#   0  SMS delivered
#
#   1  Usage/configuration error
#   2  Local/network/API communication failure
#   3  ASPSMS authentication failure
#   4  Invalid phone number
#   5  Recipient unavailable (phone off / no coverage / expired)
#   6  Mobile operator/provider failure
#   7  ASPSMS rejected request
#   8  Delivery timeout (status never became final)
#   9  Unknown failure
#

set -euxo pipefail

API="https://webapi.aspsms.com"

if [[ $# -ne 1 ]]
then
    echo "Usage: $0 PHONE_NUMBER" >&2
    exit 1
fi

PHONE="$1"
MESSAGE="$(cat -)"

if [[ -z "$MESSAGE" ]]
then
    echo "Empty message" >&2
    exit 1
fi

TRANSREF="$(date +%s)-$$-$RANDOM"

echo "T-REF: $TRANSREF" 

#
# Send SMS
#
SEND_JSON="$(
curl -fsS \
    --get \
    "$API/SendSimpleSMS" \
    --data-urlencode "Userkey=$ASPSMS_USERKEY" \
    --data-urlencode "Password=$ASPSMS_PASSWORD" \
    --data-urlencode "Recipient=$PHONE" \
    --data-urlencode "MessageData=$MESSAGE" \
    --data-urlencode "TransactionReferenceNumber=$TRANSREF"
)" || {
    echo "Communication with ASPSMS failed" >&2
    exit 2
}

ERROR_CODE=$(jq -r '.ErrorCode // empty' <<<"$SEND_JSON")
ERROR_DESC=$(jq -r '.ErrorDescription // empty' <<<"$SEND_JSON")

case "$ERROR_CODE" in
    1)
        ;;
    3|8|9)
        echo "$ERROR_DESC" >&2
        exit 3
        ;;
    20|206)
        echo "$ERROR_DESC" >&2
        exit 4
        ;;
    24)
        echo "$ERROR_DESC" >&2
        exit 7
        ;;
    "")
        echo "Unexpected response:" >&2
        echo "$SEND_JSON" >&2
        exit 2
        ;;
    *)
        echo "$ERROR_DESC" >&2
        exit 7
        ;;
esac

#
# Poll delivery status
#
#
# DeliveryStatus:
#   -1 not yet known
#    0 delivered
#    1 buffered
#    2 failed
#
# Reason codes of interest:
#
# 000 unknown subscriber
# 101 unknown subscriber
# 107 absent subscriber
# 108 delivery failed
# 105/113 SC congestion
# 118-126 network/provider failures
# 206 invalid destination address
#

for ((i=0;i<60;i++))
do
    SEC=$(($i / 10))
    # Wait at least 100ms, then go up every second by 1 second
    sleep ${SEC}.1
    echo "Fetching status..."
    STATUS_JSON="$(
    curl -fsS \
        --get \
        "$API/SendingStat03/Get" \
        --data-urlencode "Userkey=$ASPSMS_USERKEY" \
        --data-urlencode "Password=$ASPSMS_PASSWORD" \
        --data-urlencode "TransactionReferenceNumber=$TRANSREF"
    )" || continue

    DELIVERY=$(jq -r '.[0].DeliveryStatus // empty' <<<"$STATUS_JSON")
    REASON=$(jq -r '.[0].ReasonCode // ""' <<<"$STATUS_JSON")

    case "$DELIVERY" in

        0)
	    echo "Success!" >&2
            exit 0
            ;;

        1)
            continue
            ;;

        2)
	    echo "Failure: $REASON" 
            case "$REASON" in

                206|000|101)
                    exit 4
                    ;;

                107|108)
                    exit 5
                    ;;

                105|113|118|119|120|121|122|123|124|125|126)
                    exit 6
                    ;;

                *)
                    exit 9
                    ;;
            esac
            ;;

        -1|"")
            continue
            ;;

    esac

done

exit 8

#| Exit | Meaning                                                                       |
#| ---- | ----------------------------------------------------------------------------- |
#| 0    | SMS successfully delivered                                                    |
#| 1    | Usage or local configuration error                                            |
#| 2    | Unable to contact ASPSMS/API/network error                                    |
#| 3    | Authentication failure (invalid user key/password)                            |
#| 4    | Invalid or unknown recipient number                                           |
#| 5    | Recipient unreachable (phone switched off, out of coverage, delivery expired) |
#| 6    | Mobile operator/network/provider failure                                      |
#| 7    | ASPSMS rejected the request (temporary service issues, invalid request, etc.) |
#| 8    | Timed out waiting for a final delivery report                                 |
#| 9    | Delivery failed for an unclassified reason                                    |
aspsms-2.sh (4,430 bytes)   

Christian Grothoff

2026-06-26 09:13

manager   ~0028988

Sending works, confirmation check not yet.
aspsms-3.sh (7,460 bytes)   
#!/bin/bash
#
# send-sms.sh
#
# Usage:
#   echo "Hello world" | ./send-sms.sh +41791234567
#
# Environment:
#   ASPSMS_USERKEY
#   ASPSMS_PASSWORD
#
# Exit codes:
#
#   0  SMS delivered
#
#   1  Usage/configuration error
#   2  Local/network/API communication failure
#   3  ASPSMS authentication failure
#   4  Invalid phone number
#   5  Recipient unavailable (phone off / no coverage / expired)
#   6  Mobile operator/provider failure
#   7  ASPSMS rejected request
#   8  Delivery timeout (status never became final)
#   9  Unknown failure
#

set -euxo pipefail

API="https://webapi.aspsms.com"

if [[ $# -ne 1 ]]
then
    echo "Usage: $0 PHONE_NUMBER" >&2
    exit 1
fi

PHONE="$1"
MESSAGE="$(cat -)"

if [[ -z "$MESSAGE" ]]
then
    echo "Empty message" >&2
    exit 1
fi

TRANSREF="$(date +%s)-$$-$RANDOM"

echo "T-REF: $TRANSREF" 

#
# Send SMS
#
SEND_JSON="$(
curl -fsS \
    --get \
    "$API/SendSimpleSMS" \
    --data-urlencode "Userkey=$ASPSMS_USERKEY" \
    --data-urlencode "Password=$ASPSMS_PASSWORD" \
    --data-urlencode "MSISDN=$PHONE" \
    --data-urlencode "MessageData=$MESSAGE" \
    --data-urlencode "TransactionReferenceNumber=$TRANSREF"
)" || {
    echo "Communication with ASPSMS failed" >&2
    exit 2
}

ERROR_CODE=$(jq -r '.ErrorCode // empty' <<<"$SEND_JSON")
ERROR_DESC=$(jq -r '.ErrorDescription // empty' <<<"$SEND_JSON")

#1	OK
#2	Connect failed.
#3	Authorization failed.
#4	Binary file not found. Please check the location.
#5	Not enough credits available. Please recharge your account to proceed.
#6	Time out error.
#7	Transmission error. Please try it again.
#8	Invalid UserKey. Please check the spelling of the UserKey.
#9	Invalid Password.
#10	Invalid originator. A maximum of 11 characters is allowed for alphanumeric originators.
#11	Invalid message date. Please verify the data.
#12	Invalid binary data. Please verify the data.
#13	Invalid binary file. Please check the file type.
#14	Invalid MCC. Please check the number.
#15	Invalid MNC. Please check the number.
#16	Invalid XSer.
#17	Invalid URL buffered message notification string.
#18	Invalid URL delivery notification string.
#19	Invalid URL non delivery notification string.
#20	Missing a recipient. Please specify at least one recipient.
#21	Missing binary data. Please specify some data.
#22	Invalid deferred delivery time. Please check the format.
#23	Missing transaction reference number.
#24	Service temporarely not available.
#25	User access denied.
#28	No Originator Restrictions.
#29	Originator Authorization Pending.
#30	Originator Not Authorized.
#31	Originator already authorized.
#32	No Notification Recipient Restrictions.
#33	Notification Recipient Authorization Pending.
#34	Notification Recipient Not Authorized.
#35	Notification Recipient Already Authorized.
#36	Security Token authorization pending.
#37	Security Token not authorized.
#38	Security Token not found.
#39	Security Token already authorized.

case "$ERROR_CODE" in
    1)
        ;;
    3|8|9)
        echo "$ERROR_DESC" >&2
        exit 3
        ;;
    20|206)
        echo "$ERROR_DESC" >&2
        exit 4
        ;;
    24)
        echo "$ERROR_DESC" >&2
        exit 7
        ;;
    "")
        echo "Unexpected response:" >&2
        echo "$SEND_JSON" >&2
        exit 2
        ;;
    *)
        echo "$ERROR_DESC" >&2
        exit 7
        ;;
esac

#
# Poll delivery status
#
#
# DeliveryStatus:
#   -1 not yet known
#    0 delivered
#    1 buffered
#    2 failed
#
# Reason codes of interest:
#
# 000 unknown subscriber
# 101 unknown subscriber
# 103 Call Barred
# 107 absent subscriber
# 108 delivery failed (buffered / not delivered)
# 110 Protocol error
# 111 MS not qeuipment
# 105/113 SC congestion
# 118-126 network/provider failures
# 206 invalid destination address
#
# Full list:
#
#000	Unknown subscriber
#001	Service temporary not available
#002	Service temporary not available
#003	Service temporary not available
#004	Service temporary not available
#005	Service temporary not available
#006	Service temporary not available
#007	Service temporary not available
#008	Service temporary not available
#009	Illegal error code
#010	Network time-out
#100	Facility not supported
#101	Unknown subscriber
#102	Facility not provided
#103	Call barred
#104	Operation barred
#105	SC congestion
#106	Facility not supported
#107	Absent subscriber
#108	Delivery fail
#109	SC congestion
#110	Protocol error
#111	MS not equipped
#112	Unknown SC
#113	SC congestion
#114	Illegal MS
#115	MS not a subscriber
#116	Error in MS
#117	SMS lower layer not provisioned
#118	System fail
#119	PLMN system failure
#120	HLR system failure
#121	VLR system failure
#122	Previous VLR system failure
#123	Controlling MSC system failure
#124	VMSC system failure
#125	EIR system failure
#126	System failure
#127	Unexpected data value
#200	Error in address service centre
#201	Invalid absolute Validity Period
#202	Short message exceeds maximum
#203	Unable to Unpack GSM message
#204	Unable to convert to IA5 ALPHABET
#205	Invalid validity period format
#206	Invalid destination address
#207	Duplicate message submit
#208	Invalid message type indicator

for ((i=0;i<60;i++))
do
    SEC=$(($i / 10))
    # Wait at least 100ms, then go up every second by 1 second
    sleep ${SEC}.1
    echo "Fetching status..."
    STATUS_JSON="$(
    curl -fsS \
        --get \
        "$API/SendingStat03/Get" \
        --data-urlencode "Userkey=$ASPSMS_USERKEY" \
        --data-urlencode "Password=$ASPSMS_PASSWORD" \
        --data-urlencode "TransactionReferenceNumber=$TRANSREF"
    )" || continue

    jq <<< "$STATUS_JSON"
    DELIVERY=$(jq -r '.[0].DeliveryStatus // empty' <<<"$STATUS_JSON")
    REASON=$(jq -r '.[0].ReasonCode // ""' <<<"$STATUS_JSON")

    case "$DELIVERY" in

        0)
	    echo "Success!" >&2
            exit 0
            ;;

        1)
            continue
            ;;

        2)
	    echo "Failure: $REASON" 
            case "$REASON" in

                206|000|101)
                    exit 4
                    ;;

                107|108)
                    exit 5
                    ;;

                105|113|118|119|120|121|122|123|124|125|126)
                    exit 6
                    ;;

                *)
                    exit 9
                    ;;
            esac
            ;;

        -1|"")
            continue
            ;;

    esac

done

exit 8

#| Exit | Meaning                                                                       |
#| ---- | ----------------------------------------------------------------------------- |
#| 0    | SMS successfully delivered                                                    |
#| 1    | Usage or local configuration error                                            |
#| 2    | Unable to contact ASPSMS/API/network error                                    |
#| 3    | Authentication failure (invalid user key/password)                            |
#| 4    | Invalid or unknown recipient number                                           |
#| 5    | Recipient unreachable (phone switched off, out of coverage, delivery expired) |
#| 6    | Mobile operator/network/provider failure                                      |
#| 7    | ASPSMS rejected the request (temporary service issues, invalid request, etc.) |
#| 8    | Timed out waiting for a final delivery report                                 |
#| 9    | Delivery failed for an unclassified reason                                    |
aspsms-3.sh (7,460 bytes)   

Christian Grothoff

2026-06-30 13:24

manager   ~0029028

c0bac8f..bd67e05 adds a working script to challenger.git -- still needs to be deployed and adapted for merchant/KYC.

Christian Grothoff

2026-08-01 18:26

manager   ~0029343

Credentials for aspsms are now in the spec vault. Leaving final deployment to Florian...

Florian Dold

2026-09-13 14:08

manager   ~0029970

I don't want to enable aspsms before I have to way to be able to diagnose delivery. I don't see the login details in any of our secret stores yet.

Christian Grothoff

2026-11-03 09:21

manager   ~0030200

I've pushed secrets into the spec/vault.yml for all 6 (!) SMS providers.

Issue History

Date ModifiedUsernameFieldChange
2026-06-23 19:19Christian GrothoffNew Issue
2026-06-26 08:36Christian GrothoffNote Added: 0028986
2026-06-26 08:36Christian GrothoffFile Added: aspsms.sh
2026-06-26 08:55Christian GrothoffNote Added: 0028987
2026-06-26 08:55Christian GrothoffFile Added: aspsms-2.sh
2026-06-26 09:13Christian GrothoffNote Added: 0028988
2026-06-26 09:13Christian GrothoffFile Added: aspsms-3.sh
2026-06-26 13:57Christian GrothoffAssigned To => Christian Grothoff
2026-06-26 13:57Christian GrothoffStatusnew => implementing
2026-06-30 13:24Christian GrothoffNote Added: 0029028
2026-08-01 18:26Christian GrothoffAssigned ToChristian Grothoff => Florian Dold
2026-08-01 18:26Christian GrothoffNote Added: 0029343
2026-08-13 10:37Florian DoldTarget Version => 1.7
2026-09-13 14:08Florian DoldNote Added: 0029970
2026-09-13 14:09Florian DoldAssigned ToFlorian Dold => Christian Grothoff
2026-11-02 17:27Christian GrothoffAssigned ToChristian Grothoff =>
2026-11-02 17:27Christian GrothoffImplementer => Christian Grothoff
2026-11-02 17:27Christian GrothoffReviewer => Florian Dold
2026-11-02 17:27Christian GrothoffRelease signed by => Christian Grothoff
2026-11-02 17:27Christian GrothoffDeployed by => Florian Dold
2026-11-02 17:27Christian GrothoffVerifier => Christian Grothoff
2026-11-03 09:04Christian GrothoffAssigned To => Christian Grothoff
2026-11-03 09:05Christian GrothoffEstimated effort (hours) => 2
2026-11-03 09:21Christian GrothoffNote Added: 0030200
2026-11-03 09:21Christian GrothoffAssigned ToChristian Grothoff =>
2026-11-03 09:21Christian GrothoffStatusimplementing => reviewing
2026-11-03 14:06Christian GrothoffTarget Version1.7 => 1.6