java代码——华为云短信发送

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
@Slf4j
public class HwySmsMsgSendStyleImpl extends AbSmsMsgSendStyle {
    // 用于格式化鉴权头域,给“X-WSSE”参数赋值
    private static final String WSSE_HEADER_FORMAT = "UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"";
    // 用于格式化鉴权头域,给“Authorization”参数赋值
    private static final String AUTH_HEADER_VALUE = "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"";

    @Autowired
    protected HttpServletRequest request;

    @Override
    public boolean send(String phone, String content, Map<String, String> properties, String modelId) throws IOException {
        log.warn("华为短信发送---------------------------开始----------------");
        // 开发准备:APP接入地址 + 接口访问URI
        String url = properties.get("url");
        // 开发准备:APP_Key
        String appKey = properties.get("appKey");
        // 开发准备:APP_Secret
        String appSecret = properties.get("appSecret");
        // 开发准备:签名通道号
        String sender = properties.get("sender");
        // 填写短信接收人号码,多个号码之间用英文逗号分隔
        String receiver = phone;
        // 开发准备:模板ID
        String templateId = modelId;
        //sx102 id
        String extend  = properties.get("sx102Id");
//        // 开发准备:模板名称
//        String signature = properties.get("signature");
        String statusCallBack = properties.get("statusCallBack");

        //处理模板
        String unprocessedContent = properties.get("unprocessedContent");
        String parameter = properties.get("parameter");
        // 创建一个列表,存储参数值
        List<String> params = new ArrayList<>();;
        if (StringUtils.isNotBlank(parameter)){
            // 解析 JSON 数据
            JSONObject jsonData = JSON.parseObject(parameter);
            // 提取模板中的参数名
            List<String> placeholders = extractPlaceholders(unprocessedContent);
            // 遍历模板中的参数名,从数据中提取对应的参数值
            for (String placeholder : placeholders) {
                String paramValue = jsonData.getString(placeholder);
                params.add(paramValue);
            }
            // 转换列表为数组
            String[] resultArray = params.toArray(new String[0]);
        }else {
            params.add(content);
        }
        String finaPparameter = JSON.toJSONString(params);
        // 状态报告接收地址,为空或者不填表示不接收状态报告
        log.warn("平台模板内容-----"+content+";处理后模板内容-----"+JSON.toJSONString(params));
        if (StringUtils.isBlank(url) || StringUtils.isBlank(appKey) || StringUtils.isBlank(appSecret) || StringUtils.isBlank(sender) || StringUtils.isBlank(receiver) || StringUtils.isBlank(templateId)) {
            log.error(String.format("华为短信参数值不符合要求:url: %s; appKey: %s; appSecret: %s;sender: %s;receiver: %s;templateId: %s;extend: %s;",
                    url, appKey, appSecret, sender, receiver, templateId,extend));
            return false;
        }
        // 请求Body
        String body = buildRequestBody(sender, receiver, templateId, finaPparameter, statusCallBack,extend, "");

        // 请求Headers中的X-WSSE参数值
        String wsseHeader = buildWsseHeader(appKey, appSecret);

        // 如果JDK版本是1.8,可使用如下代码
        CloseableHttpClient client;
        HttpResponse response = null;
        try {
            client = HttpClients.custom()
                    .setSSLContext(
                            new SSLContextBuilder().loadTrustMaterial(null, (x509CertChain, authType) -> true).build())
                    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();

            response = client.execute(RequestBuilder.create("POST").setUri(url)
                    .addHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded")
                    .addHeader(HttpHeaders.AUTHORIZATION, AUTH_HEADER_VALUE).addHeader("X-WSSE", wsseHeader)
                    .setEntity(new StringEntity(body)).build());
        } catch (KeyManagementException e) {
            log.error(e.getMessage(), e);
        } catch (NoSuchAlgorithmException e) {
            log.error(e.getMessage(), e);
        } catch (KeyStoreException e) {
            log.error(e.getMessage(), e);
        }

        String responseEntity = EntityUtils.toString(response.getEntity());
        String code = JSON.parseObject(responseEntity).getString("code");
        String description = JSON.parseObject(responseEntity).getString("description");
        // 获取状态码
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == 200) {
            if (code.equals("000000") && description.equals("Success")) {
                log.warn("ex102Id:"+extend+"华为短信发送---------------------------结束----------------成功");
                return true;
            }
        } else {
            log.warn("ex102Id:"+extend+"华为短信发送---------------------------结束----------------statusCode");
        }
        return false;
    }

    static String buildRequestBody(String sender, String receiver, String templateId, String templateParas,
                                   String statusCallbackUrl, String extend,String signature) {

        if (null == sender || null == receiver || null == templateId || sender.isEmpty() || receiver.isEmpty()
                || templateId.isEmpty()) {
            System.out.println("buildRequestBody(): sender, receiver or templateId is null.");
            return null;
        }
        List<NameValuePair> keyValues = new ArrayList<NameValuePair>();

        keyValues.add(new BasicNameValuePair("from", sender));
        keyValues.add(new BasicNameValuePair("to", receiver));
        keyValues.add(new BasicNameValuePair("templateId", templateId));
        if (null != templateParas && !templateParas.isEmpty()) {
            keyValues.add(new BasicNameValuePair("templateParas", templateParas));
        }
        if (null != statusCallbackUrl && !statusCallbackUrl.isEmpty()) {
            keyValues.add(new BasicNameValuePair("statusCallback", statusCallbackUrl));
        }
        if (StringUtils.isNotBlank(extend)  && !extend.isEmpty()) {
            keyValues.add(new BasicNameValuePair("extend", extend));
        }
        log.warn("华为短信参数值-------------------------------"+JSON.toJSONString(keyValues));
        return URLEncodedUtils.format(keyValues, Charset.forName("UTF-8"));
    }

    static String buildWsseHeader(String appKey, String appSecret) {

        if (null == appKey || null == appSecret || appKey.isEmpty() || appSecret.isEmpty()) {
            System.out.println("buildWsseHeader(): appKey or appSecret is null.");
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        String time = sdf.format(new Date()); //Created
        String nonce = UUID.randomUUID().toString().replace("-", ""); //Nonce

        byte[] passwordDigest = DigestUtils.sha256(nonce + time + appSecret);
        String hexDigest = Hex.encodeHexString(passwordDigest);
        String passwordDigestBase64Str = Base64.getEncoder().encodeToString(hexDigest.getBytes()); //PasswordDigest

        return String.format(WSSE_HEADER_FORMAT, appKey, passwordDigestBase64Str, nonce, time);

    }

    private static List<String> extractPlaceholders(String template) {
        List<String> placeholders = new ArrayList<>();
        Pattern pattern = Pattern.compile("\\$\\{(.*?)}");
        Matcher matcher = pattern.matcher(template);
        while (matcher.find()) {
            String placeholder = matcher.group(1);
            placeholders.add(placeholder);
        }
        return placeholders;
    }

    @Override
    public String getName() {
        return "华为云短信";
    }

}

完整案例可以直接使用。

在处理将 Base64 字符串还原为图片并上传到 OBS(对象存储服务)时,常见的错误通常涉及编码格式、文件流处理或与 OBS SDK 交互的问题。以下是修复此类函数的详细步骤和注意事项。 ### Base64 解码部分 Base64 编码字符串通常以 `data:image/png;base64,` 或类似的前缀开头,表示图像类型。在解码之前,必须移除这些前缀,否则会导致解码失败。使用 `base64.b64decode()` 函数进行解码,并确保正确处理可能的异常。 ```python import base64 def decode_base64_image(base64_string): try: # 移除Base64前缀(如'data:image/png;base64,') if ',' in base64_string: base64_data = base64_string.split(',')[1] else: base64_data = base64_string # 解码Base64数据 image_data = base64.b64decode(base64_data) return image_data except Exception as e: print(f"Base64解码失败: {e}") return None ``` ### 文件保存与临时路径 为了上传到 OBS,需要将解码后的二进制数据保存为临时文件,或者直接作为字节流上传。如果选择保存为文件,可以使用 `tempfile` 模块创建临时文件,确保文件系统操作的安全性。 ```python import tempfile def save_decoded_image(image_data): try: # 创建临时文件 with tempfile.NamedTemporaryFile(delete=False, suffix='.png') as tmp_file: tmp_file.write(image_data) tmp_file_path = tmp_file.name return tmp_file_path except Exception as e: print(f"保存解码后的图片失败: {e}") return None ``` ### 上传到OBS 使用华为云提供的 OBS SDK(如 `obs` 模块),可以通过 `ObsClient` 实例实现上传功能。确保配置了正确的访问密钥、端点和桶名称。上传方式可以是文件路径或直接从内存中的字节流上传。 ```python from obs import ObsClient def upload_to_obs(file_path, object_key): # 初始化OBS客户端 obs_client = ObsClient( access_key_id='YOUR_ACCESS_KEY', secret_access_key='YOUR_SECRET_KEY', server='https://your-obs-endpoint.com' ) bucket_name = 'your-bucket-name' try: # 上传文件 resp = obs_client.putObject(bucket_name, object_key, file_path) if resp.status < 300: print("上传成功") return True else: print(f"上传失败: {resp.reason}") return False except Exception as e: print(f"OBS上传错误: {e}") return False ``` ### 完整流程整合 将上述步骤整合为一个完整的函数,确保每个环节都进行了异常处理,并提供清晰的错误提示。 ```python def process_and_upload_base64_image(base64_string, object_key): # 解码Base64字符串 image_data = decode_base64_image(base64_string) if not image_data: return False # 保存为临时文件 tmp_file_path = save_decoded_image(image_data) if not tmp_file_path: return False # 上传到OBS success = upload_to_obs(tmp_file_path, object_key) return success ``` ### 常见问题排查 1. **Base64 格式不正确**:确保输入的 Base64 字符串没有多余的字符或未正确去除前缀。 2. **文件路径问题**:检查临时文件是否成功创建,避免因权限问题导致写入失败。 3. **OBS 配置错误**:确认 `access_key_id`、`secret_access_key` 和 `server` 地址正确无误。 4. **网络连接问题**:OBS 上传依赖稳定的网络连接,若出现超时或断开,请检查网络状况。 5. **SDK 版本兼容性**:确保使用的 OBS SDK 是最新版本,以支持最新的 API 和功能。 通过以上步骤,应能有效修复将 Base64 字符串还原为图片并上传至 OBS 的函数错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值