支付寶小程序 快速示例·現(xiàn)金紅包

2020-09-16 15:00 更新

現(xiàn)金紅包為商家的小程序提供了現(xiàn)金紅包發(fā)放功能,主要應(yīng)用于企業(yè)、商家給用戶發(fā)放支付寶紅包的應(yīng)用場(chǎng)景;用戶領(lǐng)取后,紅包金額可以提現(xiàn)到支付寶余額。

商家可以配合使用多種紅包策略和玩法,如隨機(jī)金額,指定金額范圍等,并且紅包還可以分享到支付寶端外使用。

應(yīng)用案例

  • 收藏類領(lǐng)取紅包:商家可以通過(guò)現(xiàn)金紅包為自己的生活號(hào)引流,用戶在關(guān)注小程序關(guān)聯(lián)的生活號(hào)后,可以領(lǐng)取相應(yīng)數(shù)額的現(xiàn)金紅包。
  • 分享類領(lǐng)取紅包:在小程序的營(yíng)銷場(chǎng)景下,開發(fā)者可以用紅包的形式鼓勵(lì)用戶轉(zhuǎn)發(fā)小程序,通過(guò)社交裂變提高小程序的訪問(wèn)量。
  • 積分制領(lǐng)取紅包:在符合相關(guān)規(guī)定的前提下,開發(fā)者可以在小程序內(nèi)建立一定的積分體系,用戶可以用積分兌換紅包,并在余額中查看。

前提條件

獲取模板

開發(fā)者在打開小程序開發(fā)者工具時(shí),選擇 模板選取 > 開放能力 > 現(xiàn)金紅包 demo,即可進(jìn)入現(xiàn)金紅包的開發(fā)模板。

image

整體流程

使用現(xiàn)金紅包模板進(jìn)行快速開發(fā)的整體流程如下圖所示:

11111.png

開發(fā)準(zhǔn)備

簽約現(xiàn)金紅包功能

  1. 登錄 小程序開發(fā)中心,在 我的小程序 中,選擇相應(yīng)的小程序,進(jìn)入該小程序詳情頁(yè)。

  1. 在小程序詳情開發(fā)管理頁(yè)面的 功能列表 中,點(diǎn)擊右下角 添加功能 按鈕,添加 現(xiàn)金紅包 功能。

image.png

添加引入 SDK 依賴

請(qǐng)?jiān)?AlipaySDK JAVA 下載引入 AlipaySDK 開發(fā)使用。

DEMO 中使用如下配置:

<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java --><dependency>
   <groupId>com.alipay.sdk</groupId>
     <artifactId>alipay-sdk-java</artifactId>
   <version>4.8.56.ALL</version></dependency>

使用步驟

關(guān)注類領(lǐng)取紅包

功能

商家可以通過(guò)現(xiàn)金紅包為自己的生活號(hào)引流,用戶在關(guān)注小程序關(guān)聯(lián)的生活號(hào)后,可以領(lǐng)取相應(yīng)數(shù)額的現(xiàn)金紅包。

現(xiàn)金紅包 DEMO 領(lǐng)取示例:

關(guān)注領(lǐng)紅包1.png

實(shí)現(xiàn)

關(guān)注生活號(hào)組件

以 DEMO 中為例,首先為了讓用戶有關(guān)注生活號(hào)的入口,需要首先在頁(yè)面添加關(guān)注生活號(hào)組件,具體可以參考 lifestyle 組件文檔,在此不贅述。

用戶未關(guān)注生活號(hào)時(shí) isCollected 參數(shù)為 false,頁(yè)面按鈕會(huì)顯示 關(guān)注生活號(hào)領(lǐng)取紅包;點(diǎn)擊該按鈕,觸發(fā)點(diǎn)擊事件 onClickCollect() 會(huì)彈出彈窗提示用戶需要先關(guān)注生活號(hào)。

用戶點(diǎn)擊右上角關(guān)注按鈕后 isCollected 參數(shù)會(huì)被賦為 true 此時(shí)用戶界面會(huì)顯示 已關(guān)注,領(lǐng)取紅包 點(diǎn)擊此按鈕觸發(fā) onClickCollect() 事件且會(huì)調(diào)用 handleRedPacket() 函數(shù)獲取紅包;獲取成功后會(huì)在用戶界面顯示紅包信息。

關(guān)注生活號(hào)前后 Button 顯示變化邏輯

在 index.js 中,小程序頁(yè)面加載時(shí),將 收藏狀態(tài)(是否關(guān)注生活號(hào)) isCollected 初始化,默認(rèn)值為 false,即用戶未關(guān)注該生活號(hào)。

//.js
data: {
    isCollected: false, //收藏狀態(tài)
  },

小程序 axml中 關(guān)注生活號(hào)領(lǐng)取紅包 按鈕顯示內(nèi)容使用三目運(yùn)算符通過(guò)判斷用戶是否關(guān)注生活號(hào)或分享轉(zhuǎn)發(fā)來(lái)動(dòng)態(tài)顯示 button 內(nèi)容,當(dāng)用戶點(diǎn)擊右上角關(guān)注按鈕后 isCollected 參數(shù)會(huì)被賦為 true。button 中內(nèi)容則會(huì)改變?yōu)?已經(jīng)關(guān)注,領(lǐng)取紅包 ,點(diǎn)擊即可領(lǐng)取紅包。

<!-- .axml --><view class="redpacket-button">
    <button type="ghost" onTap="onClickCollect"> 
      {{ isCollected ? '已經(jīng)關(guān)注,領(lǐng)取紅包' : '關(guān)注生活號(hào)領(lǐng)紅包'}}
    </button>
    <view class="desc">
      關(guān)注生活號(hào)后可以領(lǐng)取紅包
  </view>

轉(zhuǎn)發(fā)類紅包

功能

在小程序的營(yíng)銷場(chǎng)景下,開發(fā)者可以用紅包的形式鼓勵(lì)用戶轉(zhuǎn)發(fā)小程序,通過(guò)社交裂變提高小程序的訪問(wèn)量。 現(xiàn)金紅包 DEMO 領(lǐng)取示例:

分享領(lǐng)紅包1.png

實(shí)現(xiàn)

用戶點(diǎn)擊小程序頁(yè)面的 分享領(lǐng)紅包 按鈕 ,該按鈕中定義了點(diǎn)擊事件 onClickShare(),該函數(shù)會(huì)判斷 isShared 參數(shù)的值以此確定用戶是否完成轉(zhuǎn)發(fā),默認(rèn) isShared 參數(shù)當(dāng)前值為 false ,會(huì)調(diào)用 my.showSharePanel 喚起分享頁(yè)面。

DEMO中當(dāng)分享面板展開即判定用戶轉(zhuǎn)發(fā)成功,具體業(yè)務(wù)場(chǎng)景請(qǐng)按照需求實(shí)現(xiàn)。此時(shí)會(huì)將 isShared 的值被賦為

true ,用戶頁(yè)面的按鈕信息會(huì)變?yōu)?已經(jīng)分享,領(lǐng)取紅包 ;

分享小程序前后 Button 顯示變化邏輯

在 index.js 中,小程序頁(yè)面加載時(shí),將 分享狀態(tài)(是否分享小程序) isShared 初始化,默認(rèn)值為 false,即用戶未分享該小程序。

//.js
data: {
      isShared: false, //分享狀態(tài)
  },

小程序 axml 中 分享領(lǐng)紅包 按鈕顯示內(nèi)容使用三目運(yùn)算符通過(guò)判斷用戶是否分享小程序顯示 button 內(nèi)容,當(dāng)用戶點(diǎn)擊 分享領(lǐng)紅包 按鈕后,用戶界面會(huì)彈出分享面板,此時(shí) isShared 參數(shù)會(huì)被賦為 true 。button 中內(nèi)容則會(huì)改變?yōu)?已經(jīng)分享,領(lǐng)取紅包 ,點(diǎn)擊即可領(lǐng)取紅包。

<!-- .axml --><view class="redpacket-button">
    <button type="ghost" onTap="onClickShare">
      {{ isShared ? '已經(jīng)分享,領(lǐng)取紅包' : '分享領(lǐng)紅包' }}
    </button><view class="desc">

積分制領(lǐng)取紅包

功能

在符合相關(guān)規(guī)定的前提下,開發(fā)者可以在小程序內(nèi)建立一定的積分體系,用戶可以用積分兌換紅包,并在余額中查看,如下圖所示。

現(xiàn)金紅包 DEMO 領(lǐng)取示例:

積分換取紅包.png

實(shí)現(xiàn)

DEMO 中默認(rèn)用戶積分 point 值為 9999,點(diǎn)擊 消耗積分進(jìn)行紅包兌換 按鈕,該按鈕中定義了點(diǎn)擊事件 onClickPoint() ,該函數(shù)封裝了 JSAPI my.confirm 用于彈窗提示用戶是否確定使用積分獲取紅包,當(dāng)用戶點(diǎn)擊 立即兌換 同意后調(diào)用 usePoint() 函數(shù)用于獲取積分兌換紅包結(jié)果,該函數(shù)中封裝了 JSAPI my.request 用于向后臺(tái)發(fā)送請(qǐng)求和接收返回信息。當(dāng)返回業(yè)務(wù)處理成功時(shí)會(huì)調(diào)用 handleRedPacket() 函數(shù)領(lǐng)取紅包,領(lǐng)取成功后用戶界面會(huì)顯示紅包信息。

在 index.js 中,小程序頁(yè)面加載時(shí),將用戶積分信息 Point 初始化,默認(rèn)值為 9999(僅測(cè)試使用,具體積分定義請(qǐng)開發(fā)者考慮實(shí)際場(chǎng)景實(shí)現(xiàn))。

//.js
data: {
     point:9999 //積分信息
  },

后臺(tái) controller 中使用 PointsExchangeMockImpl 實(shí)現(xiàn) PointsExchangeMock 接口進(jìn)行積分兌換紅包的業(yè)務(wù)操作,demo中直接返回 mock 信息,開發(fā)者需要根據(jù)實(shí)際情況實(shí)現(xiàn)。

  public Object pointsExchangeMock(HttpResponse response) throws Exception {
        Response alipayResponse = new Response();
        try {
            //積分兌換接口Mock,開發(fā)者可以根據(jù)自己實(shí)際的業(yè)務(wù)需要去實(shí)現(xiàn)積分兌換功能,此Demo這里直接Mock返回結(jié)果
            alipayResponse.setCode("10000");
            alipayResponse.setSuccess(true);
            alipayResponse.setMsg("Success");
            alipayResponse.setBody("Mock業(yè)務(wù)系統(tǒng)返回內(nèi)容");
            return alipayResponse;
        }catch (Exception e) {
            alipayResponse.setCode("40000");
            alipayResponse.setSuccess(false);
            alipayResponse.setMsg("false");
            alipayResponse.setBody("Mock業(yè)務(wù)系統(tǒng)返回異常");
            return alipayResponse;
        }
    }

領(lǐng)取紅包(通用代碼邏輯)

關(guān)注類、轉(zhuǎn)發(fā)類和積分制紅包在發(fā)放時(shí),都需要設(shè)置以下的紅包發(fā)放邏輯:

小程序領(lǐng)取紅包函數(shù) handleRedPacket() 函數(shù)邏輯:

//.js
 // 點(diǎn)擊領(lǐng)取紅包
  async handleRedPacket() {
    try {
      const auth = await this.getAuthCode('auth_user');
      if (auth && auth.authCode) {
        let res = null;
        if (configObj === 'dev') {//參見(jiàn) configObj 參數(shù)值參見(jiàn) config/index.js
          res = await this.getRedPacket(auth.authCode);
        } else {
          res = { ...mockRedPacketData }; //模擬數(shù)據(jù)
        }
        if (res && res.success) {
          this.setData({
            isShowRedPacket: true
          })
        }
      }
    } catch (error) {
      my.showToast({
        content: error.message
      });
    }
  },

handleRedPacket() 函數(shù)會(huì)先獲取用戶授權(quán)情況,調(diào)用 this.getAuthCode('auth_user') 函數(shù),傳入?yún)?shù)為用戶授權(quán)類型,該函數(shù)中封裝了小程序 JSAPI my.getAuthCode 用于獲取用戶授權(quán)碼;

//.js /**
   * @name getAuthCode
   * @description 獲取用戶授權(quán)
   * @param {string} [scopeCode='auth_user']
   * @returns {object}
   */
  getAuthCode(scopeCode = 'auth_user') {
    return new Promise((resolve, reject) => {
      my.getAuthCode({
        scopes: scopeCode,
        success: (auth) => {
          resolve(auth);
        },
        fail: (err) => {
          reject({ ...err, message: '獲取用戶授權(quán)失敗' });
        }
      });
    });
  },

獲取到用戶授權(quán)后 調(diào)用 getRedPacket(authCode) 函數(shù)像商戶后臺(tái)發(fā)起請(qǐng)求獲取紅包,該函數(shù)需要傳入authCode 用于后臺(tái)換取 accessToken 和 user_id,該函數(shù)中封裝了小程序JSAPI my.request 用于向后臺(tái)發(fā)送和接收返回?cái)?shù)據(jù),此處用 POST 方式將要傳給后臺(tái)的 authCode 值放在 data 中傳遞給后臺(tái)。

//.js/**
   * @name getRedPacket
   * @description 紅包接口邏輯
   * @param {string} authCode
   * @returns {object}
   */
  getRedPacket(authCode) {
    return new Promise((resolve, reject) => {
      my.request({
        url: `${URL}/alipay/demo/redpacket`,
        data: {
          authCode: authCode
        },
        success: (result) => {
          if (!result.data.success) {
            reject({
              ...result.data,
              message: '紅包領(lǐng)取失敗'
            });
          }
          resolve(result.data);
        },
        fail: (error) => {
          reject({
            ...error,
            message: '紅包領(lǐng)取異常'
          });
        }
      })
    })
  },

當(dāng)后臺(tái)處理完成業(yè)務(wù)邏輯后會(huì)將紅包信息返回( DEMO 中不做具體處理,請(qǐng)根據(jù)具體業(yè)務(wù)環(huán)境解析使用數(shù)據(jù)),當(dāng)業(yè)務(wù)處理成功時(shí)會(huì)將 isShowRedPacket 參數(shù)賦為 true (DEMO中將信息定義在axml中的 modal 標(biāo)簽中) 用戶界面就會(huì)顯示領(lǐng)取紅包的信息。

<!-- .axml --><modal
  class="redpacket-modal"
  show="{{isShowRedPacket}}"
  onModalClick="onModalClick"
  onModalClose="onModalClose"
  topImage="https://gw.alipayobjects.com/mdn/rms_283d8e/afts/img/A*7AtMQac46wYAAAAAAAAAAABkARQnAQ">
  <view slot="header">領(lǐng)取現(xiàn)金紅包</view>
  此為示例demo,請(qǐng)按文檔對(duì)接。
  <view slot="footer">我知道了</view> 
</modal>

說(shuō)明:為了良好的用戶體驗(yàn),用戶領(lǐng)取紅包后請(qǐng)注意紅包頁(yè)面定義點(diǎn)擊隱藏事件。

后臺(tái)處理紅包業(yè)務(wù)代碼:

java 代碼中請(qǐng)注意使用支付寶的 OpenAPI 向支付寶服務(wù)器發(fā)送請(qǐng)求,都需要構(gòu)造 AlipayClient 且需要配置的各項(xiàng)參數(shù),例如 小程序的公鑰,私鑰,網(wǎng)關(guān)地址,請(qǐng)求格式,字符集,簽名類型等參數(shù),建議與 DEMO 中類似編寫配置信息的工具類并且將配置信息放在 properties 文件中方便后期修改,減小代碼改動(dòng)。參考 DEMO 中 config 包與 resource 包中的 Application.properties 文件。

image.png

DEMO 中使用 server/src/main/java/com/controller/rest 下的 AlipayFundTransUniTransferControllerImpl 類實(shí)現(xiàn) AlipayFundTransUniTransferControllerl 接口,用于處理獲取紅包業(yè)務(wù),此處需要獲取前端發(fā)回的 auth_code 用戶授權(quán)碼。

調(diào)用自定義的 isBlank 方法判斷 auth_code 的值;

  public static boolean isBlank(String str) {
        int length;
        if (str != null && (length = str.length()) != 0) {
            for(int i = 0; i < length; ++i) {
                if (!Character.isWhitespace(str.charAt(i))) {
                    return false;
                }
            }
            return true;
        } else {
            return true;
        }
    }

調(diào)用 getAccessToken(auth_code) 方法傳入 auth_code:

在該方法中調(diào)用 OpenAPI alipay.system.oauth.token (換取授權(quán)訪問(wèn)令牌)對(duì)象 request 并使用 AlipayClient 的certificateExecute(request) 方法獲取 AlipaySystemOauthTokenResponse 返回,該返回類型中包含了換取 accessToken 狀態(tài)以及支付寶用戶的 user_id。

  private AlipaySystemOauthTokenResponse getAccessToken(String authCode) throws AlipayApiException {
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setGrantType("authorization_code");
        request.setCode(authCode);
        request.setRefreshToken("201208134b203fe6c11548bcabd8da5bb087a83b");
        return alipayClient.certificateExecute(request);
    }

商戶處理完成業(yè)務(wù)將信息封裝到 JSON 中 并且使用 OpenAPI 統(tǒng)一轉(zhuǎn)賬接口 (alipay.fund.trans.uni.transfer)創(chuàng)建 AlipayFundTransUniTransferRequest 對(duì)象 request 并且將數(shù)據(jù)使用 request.setBizContent() 方法保存,調(diào)用 AlipayClient 的certificateExecute(request) 方法傳入該 request 對(duì)象,向支付寶服務(wù)器發(fā)送請(qǐng)求處理。

String userId = alipaySystemOauthTokenResponse.getUserId();
 Map<String, Object> payeeInfo = new HashMap<String, Object>();
     payeeInfo.put("identity", userId);
     payeeInfo.put("identity_type", "ALIPAY_USER_ID");


     Map<String, Object> params = new HashMap<String, Object>();
     params.put("out_biz_no", System.currentTimeMillis());
     params.put("trans_amount", "0.01");
     params.put("product_code", "STD_RED_PACKET");
     params.put("biz_scene", "DIRECT_TRANSFER");
     params.put("order_title", "現(xiàn)金紅包測(cè)試Demo");
     params.put("payee_info", payeeInfo);
     params.put("business_params", "{\"sub_biz_scene\":\"REDPACKET\"}");


Object obj = JSONObject.toJSON(params);
AlipayFundTransUniTransferRequest alipayRequest = new AlipayFundTransUniTransferRequest();
alipayRequest.setBizContent(obj.toString());
AlipayFundTransUniTransferResponse alipayResponse = alipayClient.certificateExecute(alipayRequest);

最后將處理結(jié)果返回給前端頁(yè)面解析顯示。

小程序發(fā)布

代碼編寫完成后,開發(fā)者可以參考小程序 發(fā)布流程,提交開發(fā)完成的小程序。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)